blob: 416f28b66f31fa825007b3858b54b71b00832161 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreaua5357cd2021-05-09 06:14:25 +02002 * HAProxy : High Availability-enabled HTTP/TCP proxy
Willy Tarreau421ed392021-01-06 17:41:32 +01003 * Copyright 2000-2021 Willy Tarreau <willy@haproxy.org>.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
Ilya Shipitsin46a030c2020-07-05 16:36:08 +050010 * Please refer to RFC7230 - RFC7235 information about HTTP protocol, and
11 * RFC6265 for information about cookies usage. More generally, the IETF HTTP
Willy Tarreaubaaee002006-06-26 02:48:02 +020012 * Working Group's web site should be consulted for protocol related changes :
13 *
14 * http://ftp.ics.uci.edu/pub/ietf/http/
15 *
16 * Pending bugs (may be not fixed because never reproduced) :
17 * - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
18 * the proxy to terminate (no core) if the client breaks the connection during
19 * the response. Seen on 1.1.8pre4, but never reproduced. May not be related to
20 * the snprintf() bug since requests were simple (GET / HTTP/1.0), but may be
21 * related to missing setsid() (fixed in 1.1.15)
22 * - a proxy with an invalid config will prevent the startup even if disabled.
23 *
24 * ChangeLog has moved to the CHANGELOG file.
25 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020026 */
27
David Carlier7ece0962015-12-08 21:43:09 +000028#define _GNU_SOURCE
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include <ctype.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020034#include <dirent.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020035#include <sys/stat.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <sys/time.h>
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <netinet/tcp.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <signal.h>
46#include <stdarg.h>
47#include <sys/resource.h>
Tim Duesterhusdfad6a42020-04-18 16:02:47 +020048#include <sys/utsname.h>
Marc-Antoine Perennou992709b2013-02-12 10:53:52 +010049#include <sys/wait.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <time.h>
51#include <syslog.h>
Michael Schererab012dd2013-01-12 18:35:19 +010052#include <grp.h>
Willy Tarreaufc6c0322012-11-16 16:12:27 +010053#ifdef USE_CPU_AFFINITY
Willy Tarreaufc6c0322012-11-16 16:12:27 +010054#include <sched.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000055#if defined(__FreeBSD__) || defined(__DragonFly__)
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020056#include <sys/param.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000057#ifdef __FreeBSD__
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020058#include <sys/cpuset.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000059#endif
David Carlier6d5c8412017-11-29 11:02:32 +000060#include <pthread_np.h>
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020061#endif
David Carlier5e4c8e22019-09-13 05:12:58 +010062#ifdef __APPLE__
63#include <mach/mach_types.h>
64#include <mach/thread_act.h>
65#include <mach/thread_policy.h>
66#endif
Willy Tarreaufc6c0322012-11-16 16:12:27 +010067#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020068
Willy Tarreau636848a2019-04-15 19:38:50 +020069#if defined(USE_PRCTL)
70#include <sys/prctl.h>
71#endif
72
devnexen@gmail.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 Tarreau3eed10e2016-11-07 21:03:16 +0100603 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100604 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200605 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200606 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200607 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200608 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200609 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100611 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 exit(1);
613}
614
615
616
617/*********************************************************************/
618/* more specific functions ***************************************/
619/*********************************************************************/
620
William Lallemand73b85e72017-06-01 17:38:51 +0200621/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
622 * pids the signal was correctly delivered to.
623 */
William Lallemande25473c2019-04-01 11:29:56 +0200624int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200625{
626 int p;
627 int ret = 0;
628 for (p = 0; p < nb_oldpids; p++)
629 if (kill(oldpids[p], sig) == 0)
630 ret++;
631 return ret;
632}
633
William Lallemand75ea0a02017-11-15 19:02:58 +0100634/*
William Lallemand73b85e72017-06-01 17:38:51 +0200635 * remove a pid forom the olpid array and decrease nb_oldpids
636 * return 1 pid was found otherwise return 0
637 */
638
639int delete_oldpid(int pid)
640{
641 int i;
642
643 for (i = 0; i < nb_oldpids; i++) {
644 if (oldpids[i] == pid) {
645 oldpids[i] = oldpids[nb_oldpids - 1];
646 oldpids[nb_oldpids - 1] = 0;
647 nb_oldpids--;
648 return 1;
649 }
650 }
651 return 0;
652}
653
William Lallemand85b0bd92017-06-01 17:38:53 +0200654
655static void get_cur_unixsocket()
656{
657 /* if -x was used, try to update the stat socket if not available anymore */
Willy Tarreau4975d142021-03-13 11:00:33 +0100658 if (global.cli_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200659 struct bind_conf *bind_conf;
660
661 /* pass through all stats socket */
Willy Tarreau4975d142021-03-13 11:00:33 +0100662 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200663 struct listener *l;
664
665 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
666
Willy Tarreau37159062020-08-27 07:48:42 +0200667 if (l->rx.addr.ss_family == AF_UNIX &&
William Lallemand85b0bd92017-06-01 17:38:53 +0200668 (bind_conf->level & ACCESS_FD_LISTENERS)) {
669 const struct sockaddr_un *un;
670
Willy Tarreau37159062020-08-27 07:48:42 +0200671 un = (struct sockaddr_un *)&l->rx.addr;
William Lallemand85b0bd92017-06-01 17:38:53 +0200672 /* priority to old_unixsocket */
673 if (!cur_unixsocket) {
674 cur_unixsocket = strdup(un->sun_path);
675 } else {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100676 if (old_unixsocket && strcmp(un->sun_path, old_unixsocket) == 0) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200677 free(cur_unixsocket);
678 cur_unixsocket = strdup(old_unixsocket);
679 return;
680 }
681 }
682 }
683 }
684 }
685 }
686 if (!cur_unixsocket && old_unixsocket)
687 cur_unixsocket = strdup(old_unixsocket);
688}
689
William Lallemand73b85e72017-06-01 17:38:51 +0200690/*
691 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800692 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200693 */
William Lallemanda57b7e32018-12-14 21:11:31 +0100694void mworker_reload()
William Lallemand73b85e72017-06-01 17:38:51 +0200695{
William Lallemand00417412020-06-05 14:08:41 +0200696 char **next_argv = NULL;
697 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200698 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200699 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200700 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100701 struct rlimit limit;
William Lallemand7c756a82018-11-26 11:53:40 +0100702 struct per_thread_deinit_fct *ptdf;
William Lallemand73b85e72017-06-01 17:38:51 +0200703
704 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100705#if defined(USE_SYSTEMD)
706 if (global.tune.options & GTUNE_USE_SYSTEMD)
707 sd_notify(0, "RELOADING=1");
708#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200709 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
710
William Lallemandbc193052018-09-11 10:06:26 +0200711 mworker_proc_list_to_env(); /* put the children description in the env */
712
William Lallemand7c756a82018-11-26 11:53:40 +0100713 /* during the reload we must ensure that every FDs that can't be
714 * reuse (ie those that are not referenced in the proc_list)
715 * are closed or they will leak. */
716
717 /* close the listeners FD */
718 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200719
720 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
721 /* close the poller FD and the thread waker pipe FD */
722 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
723 ptdf->fct();
724 if (fdtab)
725 deinit_pollers();
726 }
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500727#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200728 /* close random device FDs */
729 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100730#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100731
Willy Tarreau8dca1952019-03-01 10:21:55 +0100732 /* restore the initial FD limits */
733 limit.rlim_cur = rlim_fd_cur_at_boot;
734 limit.rlim_max = rlim_fd_max_at_boot;
735 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
736 getrlimit(RLIMIT_NOFILE, &limit);
737 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
738 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
739 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
740 }
741
William Lallemand73b85e72017-06-01 17:38:51 +0200742 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200743 while (old_argv[old_argc])
744 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200745
William Lallemand85b0bd92017-06-01 17:38:53 +0200746 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200747 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200748 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200749 if (next_argv == NULL)
750 goto alloc_error;
751
William Lallemand00417412020-06-05 14:08:41 +0200752 /* copy the program name */
753 next_argv[next_argc++] = old_argv[0];
754
755 /* insert the new options just after argv[0] in case we have a -- */
756
William Lallemand73b85e72017-06-01 17:38:51 +0200757 /* add -sf <PID>* to argv */
William Lallemand3f128872019-04-01 11:29:59 +0200758 if (mworker_child_nb() > 0) {
759 struct mworker_proc *child;
760
William Lallemand73b85e72017-06-01 17:38:51 +0200761 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200762
763 list_for_each_entry(child, &proc_list, list) {
William Lallemand677e2f22019-11-19 17:04:18 +0100764 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1 )
William Lallemand3f128872019-04-01 11:29:59 +0200765 continue;
William Lallemand00417412020-06-05 14:08:41 +0200766 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
William Lallemand73b85e72017-06-01 17:38:51 +0200767 goto alloc_error;
768 msg = NULL;
769 }
770 }
William Lallemand2bf6d622017-06-20 11:20:23 +0200771 /* add the -x option with the stat socket */
William Lallemand85b0bd92017-06-01 17:38:53 +0200772 if (cur_unixsocket) {
William Lallemand2bf6d622017-06-20 11:20:23 +0200773 next_argv[next_argc++] = "-x";
774 next_argv[next_argc++] = (char *)cur_unixsocket;
William Lallemand85b0bd92017-06-01 17:38:53 +0200775 }
776
William Lallemand00417412020-06-05 14:08:41 +0200777 /* copy the previous options */
778 for (i = 1; i < old_argc; i++)
779 next_argv[next_argc++] = old_argv[i];
780
Christopher Faulet767a84b2017-11-24 16:50:31 +0100781 ha_warning("Reexecuting Master process\n");
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200782 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100783 execvp(next_argv[0], next_argv);
William Lallemand73b85e72017-06-01 17:38:51 +0200784
Christopher Faulet767a84b2017-11-24 16:50:31 +0100785 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100786 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100787 return;
788
William Lallemand73b85e72017-06-01 17:38:51 +0200789alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100790 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800791 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200792 return;
793}
794
William Lallemandb3f2be32018-09-11 10:06:18 +0200795static void mworker_loop()
796{
797
798#if defined(USE_SYSTEMD)
799 if (global.tune.options & GTUNE_USE_SYSTEMD)
800 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
801#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200802 /* Busy polling makes no sense in the master :-) */
803 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200804
William Lallemandbc193052018-09-11 10:06:26 +0200805 master = 1;
806
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100807 signal_unregister(SIGTTIN);
808 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100809 signal_unregister(SIGUSR1);
810 signal_unregister(SIGHUP);
811 signal_unregister(SIGQUIT);
812
William Lallemandb3f2be32018-09-11 10:06:18 +0200813 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
814 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100815 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
816 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200817 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
818 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
819 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
820 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
821
822 mworker_unblock_signals();
823 mworker_cleanlisteners();
William Lallemand27f3fa52018-12-06 14:05:20 +0100824 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200825
William Lallemandbc193052018-09-11 10:06:26 +0200826 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
827 some SIGCHLD were lost */
828
William Lallemandb3f2be32018-09-11 10:06:18 +0200829 global.nbthread = 1;
830 relative_pid = 1;
831 pid_bit = 1;
Willy Tarreaua38a7172019-02-02 17:11:28 +0100832 all_proc_mask = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200833
William Lallemand2672eb92018-12-14 15:52:39 +0100834#ifdef USE_THREAD
835 tid_bit = 1;
836 all_threads_mask = 1;
837#endif
838
William Lallemandb3f2be32018-09-11 10:06:18 +0200839 jobs++; /* this is the "master" job, we want to take care of the
840 signals even if there is no listener so the poll loop don't
841 leave */
842
843 fork_poller();
Willy Tarreaub4f7cc32019-05-03 09:27:30 +0200844 run_thread_poll_loop(0);
William Lallemandb3f2be32018-09-11 10:06:18 +0200845}
William Lallemandcb11fd22017-06-01 17:38:52 +0200846
847/*
848 * Reexec the process in failure mode, instead of exiting
849 */
850void reexec_on_failure()
851{
852 if (!atexit_flag)
853 return;
854
855 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
856
Christopher Faulet767a84b2017-11-24 16:50:31 +0100857 ha_warning("Reexecuting Master process in waitpid mode\n");
William Lallemandcb11fd22017-06-01 17:38:52 +0200858 mworker_reload();
William Lallemandcb11fd22017-06-01 17:38:52 +0200859}
William Lallemand73b85e72017-06-01 17:38:51 +0200860
861
862/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200863 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
864 * a signal zero to all subscribers. This means that it's as easy as
865 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200866 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100867static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200868{
869 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200870 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100871 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872}
873
874/*
875 * upon SIGTTOU, we pause everything
876 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100877static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878{
Willy Tarreau775e0012020-09-24 16:36:26 +0200879 if (protocol_pause_all() & ERR_FATAL) {
880 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200881 ha_warning("%s", msg);
882 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200883 soft_stop();
884 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100885 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886}
887
888/*
889 * upon SIGTTIN, let's have a soft stop.
890 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100891static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892{
Willy Tarreau775e0012020-09-24 16:36:26 +0200893 if (protocol_resume_all() & ERR_FATAL) {
894 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 +0200895 ha_warning("%s", msg);
896 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200897 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898}
899
900/*
901 * this function dumps every server's state when the process receives SIGHUP.
902 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100903static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100905 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906
Christopher Faulet767a84b2017-11-24 16:50:31 +0100907 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 while (p) {
909 struct server *s = p->srv;
910
911 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
912 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100913 chunk_printf(&trash,
914 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
915 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200916 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100917 s->cur_sess, s->nbpend, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200918 ha_warning("%s\n", trash.area);
919 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920 s = s->next;
921 }
922
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200923 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
924 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100925 chunk_printf(&trash,
926 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
927 p->id,
928 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 +0200929 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100930 chunk_printf(&trash,
931 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
932 p->id,
933 (p->srv_bck) ? "is running on backup servers" : "has no server available",
934 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 +0200935 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100936 chunk_printf(&trash,
937 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
938 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
939 p->id, p->srv_act, p->srv_bck,
940 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 +0200941 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200942 ha_warning("%s\n", trash.area);
943 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944
945 p = p->next;
946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947}
948
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100949static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200951 /* dump memory usage then free everything possible */
952 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100953 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954}
955
William Lallemande1340412017-12-28 16:09:36 +0100956/*
957 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
958 * If <fd> < 0, it opens /dev/null and use it to dup
959 *
960 * In the case of chrooting, you have to open /dev/null before the chroot, and
961 * pass the <fd> to this function
962 */
963static void stdio_quiet(int fd)
964{
965 if (fd < 0)
966 fd = open("/dev/null", O_RDWR, 0);
967
968 if (fd > -1) {
969 fclose(stdin);
970 fclose(stdout);
971 fclose(stderr);
972
973 dup2(fd, 0);
974 dup2(fd, 1);
975 dup2(fd, 2);
976 if (fd > 2)
977 close(fd);
978 return;
979 }
980
981 ha_alert("Cannot open /dev/null\n");
982 exit(EXIT_FAILURE);
983}
984
985
Joseph Herlant03420902018-11-15 10:41:50 -0800986/* This function checks if cfg_cfgfiles contains directories.
987 * If it finds one, it adds all the files (and only files) it contains
988 * in cfg_cfgfiles in place of the directory (and removes the directory).
989 * It adds the files in lexical order.
990 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200991 * It doesn't add files with name starting with '.'
992 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100993static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200994{
995 struct wordlist *wl, *wlb;
996 char *err = NULL;
997
998 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
999 struct stat file_stat;
1000 struct dirent **dir_entries = NULL;
1001 int dir_entries_nb;
1002 int dir_entries_it;
1003
1004 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001005 ha_alert("Cannot open configuration file/directory %s : %s\n",
1006 wl->s,
1007 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001008 exit(1);
1009 }
1010
1011 if (!S_ISDIR(file_stat.st_mode))
1012 continue;
1013
1014 /* from this point wl->s is a directory */
1015
1016 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1017 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001018 ha_alert("Cannot open configuration directory %s : %s\n",
1019 wl->s,
1020 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001021 exit(1);
1022 }
1023
1024 /* for each element in the directory wl->s */
1025 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1026 struct dirent *dir_entry = dir_entries[dir_entries_it];
1027 char *filename = NULL;
1028 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1029
1030 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001031 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001032 */
1033 if (dir_entry->d_name[0] == '.' ||
1034 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1035 goto next_dir_entry;
1036
1037 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001038 ha_alert("Cannot load configuration files %s : out of memory.\n",
1039 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001040 exit(1);
1041 }
1042
1043 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001044 ha_alert("Cannot open configuration file %s : %s\n",
1045 wl->s,
1046 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001047 exit(1);
1048 }
1049
1050 /* don't add anything else than regular file in cfg_cfgfiles
1051 * this way we avoid loops
1052 */
1053 if (!S_ISREG(file_stat.st_mode))
1054 goto next_dir_entry;
1055
1056 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001057 ha_alert("Cannot load configuration files %s : %s\n",
1058 filename,
1059 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001060 exit(1);
1061 }
1062
1063next_dir_entry:
1064 free(filename);
1065 free(dir_entry);
1066 }
1067
1068 free(dir_entries);
1069
1070 /* remove the current directory (wl) from cfg_cfgfiles */
1071 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001072 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001073 free(wl);
1074 }
1075
1076 free(err);
1077}
1078
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079/*
William Lallemand73b85e72017-06-01 17:38:51 +02001080 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001081 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001082 * Return an allocated copy of argv
1083 */
1084
1085static char **copy_argv(int argc, char **argv)
1086{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001087 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001088
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001089 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001090 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001091 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001092 return NULL;
1093 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001094 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001095
William Lallemanddf6c5a82020-06-04 17:40:23 +02001096 /* first copy argv[0] */
1097 *newargv++ = *argv++;
1098 argc--;
1099
1100 while (argc > 0) {
1101 if (**argv != '-') {
1102 /* non options are copied but will fail in the argument parser */
1103 *newargv++ = *argv++;
1104 argc--;
1105
1106 } else {
1107 char *flag;
1108
1109 flag = *argv + 1;
1110
1111 if (flag[0] == '-' && flag[1] == 0) {
1112 /* "--\0" copy every arguments till the end of argv */
1113 *newargv++ = *argv++;
1114 argc--;
1115
1116 while (argc > 0) {
1117 *newargv++ = *argv++;
1118 argc--;
1119 }
1120 } else {
1121 switch (*flag) {
1122 case 's':
1123 /* -sf / -st and their parameters are ignored */
1124 if (flag[1] == 'f' || flag[1] == 't') {
1125 argc--;
1126 argv++;
1127 /* The list can't contain a negative value since the only
1128 way to know the end of this list is by looking for the
1129 next option or the end of the options */
1130 while (argc > 0 && argv[0][0] != '-') {
1131 argc--;
1132 argv++;
1133 }
William Lallemand398da622020-09-02 16:12:23 +02001134 } else {
1135 argc--;
1136 argv++;
1137
William Lallemanddf6c5a82020-06-04 17:40:23 +02001138 }
1139 break;
1140
1141 case 'x':
1142 /* this option and its parameter are ignored */
1143 argc--;
1144 argv++;
1145 if (argc > 0) {
1146 argc--;
1147 argv++;
1148 }
1149 break;
1150
1151 case 'C':
1152 case 'n':
1153 case 'm':
1154 case 'N':
1155 case 'L':
1156 case 'f':
1157 case 'p':
1158 case 'S':
1159 /* these options have only 1 parameter which must be copied and can start with a '-' */
1160 *newargv++ = *argv++;
1161 argc--;
1162 if (argc == 0)
1163 goto error;
1164 *newargv++ = *argv++;
1165 argc--;
1166 break;
1167 default:
1168 /* for other options just copy them without parameters, this is also done
1169 * for options like "--foo", but this will fail in the argument parser.
1170 * */
1171 *newargv++ = *argv++;
1172 argc--;
1173 break;
1174 }
William Lallemand73b85e72017-06-01 17:38:51 +02001175 }
1176 }
William Lallemand73b85e72017-06-01 17:38:51 +02001177 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001178
William Lallemanddf6c5a82020-06-04 17:40:23 +02001179 return retargv;
1180
1181error:
1182 free(retargv);
1183 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001184}
1185
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001186
1187/* Performs basic random seed initialization. The main issue with this is that
1188 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1189 * which means that there will only be 4 billion possible random sequences once
1190 * srandom() is called, regardless of the internal state. Not calling it is
1191 * even worse as we'll always produce the same randoms sequences. What we do
1192 * here is to create an initial sequence from various entropy sources, hash it
1193 * using SHA1 and keep the resulting 160 bits available globally.
1194 *
1195 * We initialize the current process with the first 32 bits before starting the
1196 * polling loop, where all this will be changed to have process specific and
1197 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001198 *
1199 * Before starting threads, it's still possible to call random() as srandom()
1200 * is initialized from this, but after threads and/or processes are started,
1201 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001202 */
1203static void ha_random_boot(char *const *argv)
1204{
1205 unsigned char message[256];
1206 unsigned char *m = message;
1207 struct timeval tv;
1208 blk_SHA_CTX ctx;
1209 unsigned long l;
1210 int fd;
1211 int i;
1212
1213 /* start with current time as pseudo-random seed */
1214 gettimeofday(&tv, NULL);
1215 write_u32(m, tv.tv_sec); m += 4;
1216 write_u32(m, tv.tv_usec); m += 4;
1217
1218 /* PID and PPID add some OS-based randomness */
1219 write_u16(m, getpid()); m += 2;
1220 write_u16(m, getppid()); m += 2;
1221
1222 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1223 fd = open("/dev/urandom", O_RDONLY);
1224 if (fd >= 0) {
1225 i = read(fd, m, 20);
1226 if (i > 0)
1227 m += i;
1228 close(fd);
1229 }
1230
1231 /* take up to 160 bits bytes from openssl (non-blocking) */
1232#ifdef USE_OPENSSL
1233 if (RAND_bytes(m, 20) == 1)
1234 m += 20;
1235#endif
1236
1237 /* take 160 bits from existing random in case it was already initialized */
1238 for (i = 0; i < 5; i++) {
1239 write_u32(m, random());
1240 m += 4;
1241 }
1242
1243 /* stack address (benefit form operating system's ASLR) */
1244 l = (unsigned long)&m;
1245 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1246
1247 /* argv address (benefit form operating system's ASLR) */
1248 l = (unsigned long)&argv;
1249 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1250
1251 /* use tv_usec again after all the operations above */
1252 gettimeofday(&tv, NULL);
1253 write_u32(m, tv.tv_usec); m += 4;
1254
1255 /*
1256 * At this point, ~84-92 bytes have been used
1257 */
1258
1259 /* finish with the hostname */
1260 strncpy((char *)m, hostname, message + sizeof(message) - m);
1261 m += strlen(hostname);
1262
1263 /* total message length */
1264 l = m - message;
1265
1266 memset(&ctx, 0, sizeof(ctx));
1267 blk_SHA1_Init(&ctx);
1268 blk_SHA1_Update(&ctx, message, l);
1269 blk_SHA1_Final(boot_seed, &ctx);
1270
1271 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001272 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001273}
1274
Willy Tarreau5a023f02019-03-01 14:19:31 +01001275/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1276 * setting, and returns it. It may return -1 meaning "unlimited" if some
1277 * unlimited proxies have been found and the global.maxconn value is not yet
1278 * set. It may also return a value greater than maxconn if it's not yet set.
1279 * Note that a value of zero means there is no need for pipes. -1 is never
1280 * returned if global.maxconn is valid.
1281 */
1282static int compute_ideal_maxpipes()
1283{
1284 struct proxy *cur;
1285 int nbfe = 0, nbbe = 0;
1286 int unlimited = 0;
1287 int pipes;
1288 int max;
1289
1290 for (cur = proxies_list; cur; cur = cur->next) {
1291 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1292 if (cur->cap & PR_CAP_FE) {
1293 max = cur->maxconn;
1294 nbfe += max;
1295 if (!max) {
1296 unlimited = 1;
1297 break;
1298 }
1299 }
1300 if (cur->cap & PR_CAP_BE) {
1301 max = cur->fullconn ? cur->fullconn : global.maxconn;
1302 nbbe += max;
1303 if (!max) {
1304 unlimited = 1;
1305 break;
1306 }
1307 }
1308 }
1309 }
1310
1311 pipes = MAX(nbfe, nbbe);
1312 if (global.maxconn) {
1313 if (pipes > global.maxconn || unlimited)
1314 pipes = global.maxconn;
1315 } else if (unlimited) {
1316 pipes = -1;
1317 }
1318
1319 return pipes >= 4 ? pipes / 4 : pipes;
1320}
1321
Willy Tarreauac350932019-03-01 15:43:14 +01001322/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1323 * rlimits and computes an ideal maxconn. It's meant to be called only when
1324 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001325 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1326 * default 100) is returned as it is expected that it will even run on tight
1327 * environments, and will maintain compatibility with previous packages that
1328 * used to rely on this value as the default one. The system will emit a
1329 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001330 */
1331static int compute_ideal_maxconn()
1332{
1333 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1334 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1335 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001336 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001337 int maxconn;
1338
1339 /* we have to take into account these elements :
1340 * - number of engine_fds, which inflates the number of FD needed per
1341 * connection by this number.
1342 * - number of pipes per connection on average : for the unlimited
1343 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1344 * fixed value of 2*pipes.
1345 * - two FDs per connection
1346 */
1347
1348 /* subtract listeners and checks */
1349 remain -= global.maxsock;
1350
Willy Tarreau3f200852019-03-14 19:13:17 +01001351 /* one epoll_fd/kqueue_fd per thread */
1352 remain -= global.nbthread;
1353
1354 /* one wake-up pipe (2 fd) per thread */
1355 remain -= 2 * global.nbthread;
1356
Willy Tarreauac350932019-03-01 15:43:14 +01001357 /* Fixed pipes values : we only subtract them if they're not larger
1358 * than the remaining FDs because pipes are optional.
1359 */
1360 if (pipes >= 0 && pipes * 2 < remain)
1361 remain -= pipes * 2;
1362
1363 if (pipes < 0) {
1364 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1365 * = maxconn * (2 + 0.5 + engine_fds)
1366 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1367 */
1368 maxconn = 2 * remain / (5 + 2 * engine_fds);
1369 } else {
1370 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1371 * = maxconn * (2 + engine_fds)
1372 */
1373 maxconn = remain / (2 + engine_fds);
1374 }
1375
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001376 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001377}
1378
Willy Tarreaua409f302020-03-10 17:08:53 +01001379/* computes the estimated maxsock value for the given maxconn based on the
1380 * possibly set global.maxpipes and existing partial global.maxsock. It may
1381 * temporarily change global.maxconn for the time needed to propagate the
1382 * computations, and will reset it.
1383 */
1384static int compute_ideal_maxsock(int maxconn)
1385{
1386 int maxpipes = global.maxpipes;
1387 int maxsock = global.maxsock;
1388
1389
1390 if (!maxpipes) {
1391 int old_maxconn = global.maxconn;
1392
1393 global.maxconn = maxconn;
1394 maxpipes = compute_ideal_maxpipes();
1395 global.maxconn = old_maxconn;
1396 }
1397
1398 maxsock += maxconn * 2; /* each connection needs two sockets */
1399 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1400 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1401 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1402
1403 /* compute fd used by async engines */
1404 if (global.ssl_used_async_engines) {
1405 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1406
1407 maxsock += maxconn * sides * global.ssl_used_async_engines;
1408 }
1409 return maxsock;
1410}
1411
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001412/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001413 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1414 * value is accepted, non-zero otherwise. This is used to determine if an
1415 * automatic limit may be applied or not. When it is not, the caller knows that
1416 * the highest we can do is the rlim_max at boot. In case of error, we return
1417 * that the setting is possible, so that we defer the error processing to the
1418 * final stage in charge of enforcing this.
1419 */
1420static int check_if_maxsock_permitted(int maxsock)
1421{
1422 struct rlimit orig_limit, test_limit;
1423 int ret;
1424
1425 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1426 return 1;
1427
1428 /* don't go further if we can't even set to what we have */
1429 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1430 return 1;
1431
1432 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1433 test_limit.rlim_cur = test_limit.rlim_max;
1434 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1435
1436 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1437 return 1;
1438
1439 return ret == 0;
1440}
1441
Amaury Denoyelle484454d2021-05-05 16:18:45 +02001442void mark_tainted(const enum tainted_flags flag)
1443{
1444 HA_ATOMIC_OR(&tainted, flag);
1445}
1446
1447unsigned int get_tainted()
1448{
1449 int tainted_state;
1450 HA_ATOMIC_STORE(&tainted_state, tainted);
1451 return tainted_state;
1452}
Willy Tarreau304e17e2020-03-10 17:54:54 +01001453
William Lallemand73b85e72017-06-01 17:38:51 +02001454/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 * This function initializes all the necessary variables. It only returns
1456 * if everything is OK. If something fails, it exits.
1457 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001458static void init(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459{
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 int arg_mode = 0; /* MODE_DEBUG, ... */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461 char *tmp;
1462 char *cfg_pidfile = NULL;
Willy Tarreau058e9072009-07-20 09:30:05 +02001463 int err_code = 0;
Maxime de Roucy0f503922016-05-13 23:52:55 +02001464 char *err_msg = NULL;
Willy Tarreau477ecd82010-01-03 21:12:30 +01001465 struct wordlist *wl;
Kevinm48936af2010-12-22 16:08:21 +00001466 char *progname;
Willy Tarreau576132e2011-09-10 19:26:56 +02001467 char *change_dir = NULL;
Christopher Fauletd7c91962015-04-30 11:48:27 +02001468 struct proxy *px;
Willy Tarreaue6945732016-12-21 19:57:00 +01001469 struct post_check_fct *pcf;
Willy Tarreauac350932019-03-01 15:43:14 +01001470 int ideal_maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471
Christopher Faulete3a5e352017-10-24 13:53:54 +02001472 global.mode = MODE_STARTING;
William Lallemand00417412020-06-05 14:08:41 +02001473 old_argv = copy_argv(argc, argv);
1474 if (!old_argv) {
William Lallemanddf6c5a82020-06-04 17:40:23 +02001475 ha_alert("failed to copy argv.\n");
1476 exit(1);
1477 }
William Lallemand73b85e72017-06-01 17:38:51 +02001478
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001479 if (!init_trash_buffers(1)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001480 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet748919a2017-07-26 14:59:46 +02001481 exit(1);
1482 }
David du Colombier7af46052012-05-16 14:16:48 +02001483
Emeric Brun2b920a12010-09-23 18:30:22 +02001484 /* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
1485 * the string in case of truncation, and at least FreeBSD appears not to do
1486 * it.
1487 */
1488 memset(hostname, 0, sizeof(hostname));
1489 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001490
1491 if ((localpeer = strdup(hostname)) == NULL) {
1492 ha_alert("Cannot allocate memory for local peer.\n");
1493 exit(EXIT_FAILURE);
1494 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001495 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Emeric Brun2b920a12010-09-23 18:30:22 +02001496
William Lallemand24c928c2020-01-14 17:58:18 +01001497 /* we were in mworker mode, we should restart in mworker mode */
1498 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1499 global.mode |= MODE_MWORKER;
1500
Willy Tarreaubaaee002006-06-26 02:48:02 +02001501 /*
1502 * Initialize the previously static variables.
1503 */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001504
Willy Tarreau173d9952018-01-26 21:48:23 +01001505 totalconn = actconn = listeners = stopping = 0;
Cyril Bonté203ec5a2017-03-23 22:44:13 +01001506 killed = 0;
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001507
Willy Tarreaubaaee002006-06-26 02:48:02 +02001508
1509#ifdef HAPROXY_MEMMAX
Willy Tarreau70060452015-12-14 12:46:07 +01001510 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001511#endif
1512
Benoit GARNIERb413c2a2016-03-27 11:08:03 +02001513 tzset();
Willy Tarreauc4c80fb2021-04-11 15:00:34 +02001514 tv_init_process_date();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515 start_date = now;
1516
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001517 ha_random_boot(argv);
Willy Tarreau84310e22014-02-14 11:59:04 +01001518
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001519 if (init_acl() != 0)
1520 exit(1);
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001521
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001522 /* Initialise lua. */
1523 hlua_init();
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001524
Christopher Fauletff2613e2016-11-09 11:36:17 +01001525 /* Initialize process vars */
Willy Tarreaucfc4f242021-05-08 11:41:28 +02001526 vars_init(&proc_vars, SCOPE_PROC);
Christopher Fauletff2613e2016-11-09 11:36:17 +01001527
Willy Tarreau43b78992009-01-25 15:42:27 +01001528 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001529#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001530 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001531#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001532#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001533 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001534#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001535#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001536 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001537#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001538#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001539 global.tune.options |= GTUNE_USE_EVPORTS;
1540#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001541#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001542 global.tune.options |= GTUNE_USE_SPLICE;
1543#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001544#if defined(USE_GETADDRINFO)
1545 global.tune.options |= GTUNE_USE_GAI;
1546#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001547#if defined(SO_REUSEPORT)
1548 global.tune.options |= GTUNE_USE_REUSEPORT;
1549#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001550#ifdef USE_THREAD
1551 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1552#endif
William Dauchya5194602020-03-28 19:29:58 +01001553 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554
1555 pid = getpid();
1556 progname = *argv;
1557 while ((tmp = strchr(progname, '/')) != NULL)
1558 progname = tmp + 1;
1559
Kevinm48936af2010-12-22 16:08:21 +00001560 /* the process name is used for the logs only */
Eric Salama7cea6062020-10-02 11:58:19 +02001561 chunk_initlen(&global.log_tag, strdup(progname), strlen(progname), strlen(progname));
1562 if (b_orig(&global.log_tag) == NULL) {
1563 chunk_destroy(&global.log_tag);
1564 ha_alert("Cannot allocate memory for log_tag.\n");
1565 exit(EXIT_FAILURE);
1566 }
Kevinm48936af2010-12-22 16:08:21 +00001567
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 argc--; argv++;
1569 while (argc > 0) {
1570 char *flag;
1571
1572 if (**argv == '-') {
1573 flag = *argv+1;
1574
1575 /* 1 arg */
1576 if (*flag == 'v') {
1577 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001578 if (flag[1] == 'v') /* -vv */
1579 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580 exit(0);
1581 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001582#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001584 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001586#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001588 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001590#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001591 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001592 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001593#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001594#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001595 else if (*flag == 'd' && flag[1] == 'v')
1596 global.tune.options &= ~GTUNE_USE_EVPORTS;
1597#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001598#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001599 else if (*flag == 'd' && flag[1] == 'S')
1600 global.tune.options &= ~GTUNE_USE_SPLICE;
1601#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001602#if defined(USE_GETADDRINFO)
1603 else if (*flag == 'd' && flag[1] == 'G')
1604 global.tune.options &= ~GTUNE_USE_GAI;
1605#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001606#if defined(SO_REUSEPORT)
1607 else if (*flag == 'd' && flag[1] == 'R')
1608 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1609#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001610 else if (*flag == 'd' && flag[1] == 'V')
1611 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612 else if (*flag == 'V')
1613 arg_mode |= MODE_VERBOSE;
1614 else if (*flag == 'd' && flag[1] == 'b')
1615 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001616 else if (*flag == 'd' && flag[1] == 'D')
1617 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001618 else if (*flag == 'd' && flag[1] == 'W')
1619 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreau6e064432012-05-08 15:40:42 +02001620 else if (*flag == 'd' && flag[1] == 'M')
1621 mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001622 else if (*flag == 'd' && flag[1] == 'r')
1623 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624 else if (*flag == 'd')
1625 arg_mode |= MODE_DEBUG;
1626 else if (*flag == 'c')
1627 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001628 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001629 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001630 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001631 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001632#if defined(USE_SYSTEMD)
1633 global.tune.options |= GTUNE_USE_SYSTEMD;
1634#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001635 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 +01001636 usage(progname);
1637#endif
1638 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001639 else if (*flag == 'W')
1640 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641 else if (*flag == 'q')
1642 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001643 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001644 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001645 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001646 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001647 }
William Lallemand4fc09692017-06-19 16:37:19 +02001648 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001649 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001650 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001651
Olivier Houchardf73629d2017-04-05 22:33:04 +02001652 argv++;
1653 argc--;
1654 }
William Lallemande7361152018-10-26 14:47:36 +02001655 else if (*flag == 'S') {
1656 struct wordlist *c;
1657
William Lallemanda6b32492020-06-04 23:49:20 +02001658 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001659 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1660 usage(progname);
1661 }
1662 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1663 ha_alert("Cannot allocate memory\n");
1664 exit(EXIT_FAILURE);
1665 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001666 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001667
1668 argv++;
1669 argc--;
1670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001671 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1672 /* list of pids to finish ('f') or terminate ('t') */
1673
1674 if (flag[1] == 'f')
1675 oldpids_sig = SIGUSR1; /* finish then exit */
1676 else
1677 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001678 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001679 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001680 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1681 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001682 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001683 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001684 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001685 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001686 errno = 0;
1687 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1688 if (errno) {
1689 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1690 flag,
1691 *argv, strerror(errno));
1692 exit(1);
1693 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001694 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001695 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001696 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1697 flag, endptr);
1698 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001699 }
Chris Lane236062f2018-02-05 23:15:44 +00001700 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001701 if (oldpids[nb_oldpids] <= 0)
1702 usage(progname);
1703 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001704 }
1705 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001706 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1707 /* now that's a cfgfile list */
1708 argv++; argc--;
1709 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001710 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001711 ha_alert("Cannot load configuration file/directory %s : %s\n",
1712 *argv,
1713 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001714 exit(1);
1715 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001716 argv++; argc--;
1717 }
1718 break;
1719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 else { /* >=2 args */
1721 argv++; argc--;
1722 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001723 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724
1725 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001726 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001728 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001730 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001731 free(localpeer);
1732 if ((localpeer = strdup(*argv)) == NULL) {
1733 ha_alert("Cannot allocate memory for local peer.\n");
1734 exit(EXIT_FAILURE);
1735 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001736 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001737 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001738 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001739 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001740 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001741 ha_alert("Cannot load configuration file/directory %s : %s\n",
1742 *argv,
1743 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001744 exit(1);
1745 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001746 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001747 case 'p' : cfg_pidfile = *argv; break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001748 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001749 }
1750 }
1751 }
1752 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001753 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 argv++; argc--;
1755 }
1756
Christopher Faulete3a5e352017-10-24 13:53:54 +02001757 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001758 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
1759 | MODE_DIAG));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001760
William Lallemand944e6192018-11-21 15:48:31 +01001761 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001762 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001763 global.mode |= MODE_MWORKER_WAIT;
1764 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001765 }
1766
Willy Tarreau7a534eb2021-07-21 10:01:36 +02001767 if ((global.mode & (MODE_MWORKER | MODE_CHECK)) == MODE_MWORKER &&
1768 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001769 atexit_flag = 1;
1770 atexit(reexec_on_failure);
1771 }
1772
Willy Tarreau576132e2011-09-10 19:26:56 +02001773 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001774 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001775 exit(1);
1776 }
1777
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001779
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001780#ifdef USE_CPU_AFFINITY
1781 {
1782 int i;
1783 for (i = 0; i < MAX_PROCS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001784 ha_cpuset_zero(&cpu_map.proc[i]);
1785 ha_cpuset_zero(&cpu_map.proc_t1[i]);
Willy Tarreau26f42a02021-05-14 08:26:38 +02001786 }
1787 for (i = 0; i < MAX_THREADS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001788 ha_cpuset_zero(&cpu_map.thread[i]);
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001789 }
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001790 }
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001791#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001792
William Lallemand944e6192018-11-21 15:48:31 +01001793 /* in wait mode, we don't try to read the configuration files */
1794 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001795 char *env_cfgfiles = NULL;
1796 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001797
William Lallemand944e6192018-11-21 15:48:31 +01001798 /* handle cfgfiles that are actually directories */
1799 cfgfiles_expand_directories();
1800
1801 if (LIST_ISEMPTY(&cfg_cfgfiles))
1802 usage(progname);
1803
1804
1805 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1806 int ret;
1807
Christopher Faulet4e366822021-01-12 18:57:38 +01001808 if (env_err == 0) {
1809 if (!memprintf(&env_cfgfiles, "%s%s%s",
1810 (env_cfgfiles ? env_cfgfiles : ""),
1811 (env_cfgfiles ? ";" : ""), wl->s))
1812 env_err = 1;
1813 }
William Lallemand7b302d82019-05-20 11:15:37 +02001814
William Lallemand944e6192018-11-21 15:48:31 +01001815 ret = readcfgfile(wl->s);
1816 if (ret == -1) {
1817 ha_alert("Could not open configuration file %s : %s\n",
1818 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01001819 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001820 exit(1);
1821 }
1822 if (ret & (ERR_ABORT|ERR_FATAL))
1823 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1824 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01001825 if (err_code & ERR_ABORT) {
1826 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001827 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01001828 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001829 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001830
William Lallemand944e6192018-11-21 15:48:31 +01001831 /* do not try to resolve arguments nor to spot inconsistencies when
1832 * the configuration contains fatal errors caused by files not found
1833 * or failed memory allocations.
1834 */
1835 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1836 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01001837 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001838 exit(1);
1839 }
Christopher Faulet4e366822021-01-12 18:57:38 +01001840 if (env_err) {
1841 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1842 exit(1);
1843 }
1844 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1845 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001846
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001847 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001848 if (global.mode & MODE_MWORKER) {
1849 int proc;
William Lallemand16dd1b32018-11-19 18:46:18 +01001850 struct mworker_proc *tmproc;
1851
William Lallemand482f9a92019-04-12 16:15:00 +02001852 setenv("HAPROXY_MWORKER", "1", 1);
1853
William Lallemand16dd1b32018-11-19 18:46:18 +01001854 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1855
William Lallemandf3a86832019-04-01 11:29:58 +02001856 tmproc = calloc(1, sizeof(*tmproc));
William Lallemand16dd1b32018-11-19 18:46:18 +01001857 if (!tmproc) {
1858 ha_alert("Cannot allocate process structures.\n");
1859 exit(EXIT_FAILURE);
1860 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001861 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01001862 tmproc->reloads = 0;
1863 tmproc->relative_pid = 0;
1864 tmproc->pid = pid;
1865 tmproc->timestamp = start_date.tv_sec;
1866 tmproc->ipc_fd[0] = -1;
1867 tmproc->ipc_fd[1] = -1;
1868
1869 proc_self = tmproc;
1870
Willy Tarreau2b718102021-04-21 07:32:39 +02001871 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01001872 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001873
1874 for (proc = 0; proc < global.nbproc; proc++) {
William Lallemandce83b4a2018-10-26 14:47:30 +02001875
William Lallemandf3a86832019-04-01 11:29:58 +02001876 tmproc = calloc(1, sizeof(*tmproc));
William Lallemandce83b4a2018-10-26 14:47:30 +02001877 if (!tmproc) {
1878 ha_alert("Cannot allocate process structures.\n");
1879 exit(EXIT_FAILURE);
1880 }
1881
William Lallemand8f7069a2019-04-12 16:09:23 +02001882 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02001883 tmproc->pid = -1;
1884 tmproc->reloads = 0;
William Lallemande3683302018-11-19 18:46:17 +01001885 tmproc->timestamp = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001886 tmproc->relative_pid = 1 + proc;
William Lallemand550db6d2018-11-06 17:37:12 +01001887 tmproc->ipc_fd[0] = -1;
1888 tmproc->ipc_fd[1] = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001889
1890 if (mworker_cli_sockpair_new(tmproc, proc) < 0) {
1891 exit(EXIT_FAILURE);
1892 }
1893
Willy Tarreau2b718102021-04-21 07:32:39 +02001894 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemandce83b4a2018-10-26 14:47:30 +02001895 }
William Lallemand944e6192018-11-21 15:48:31 +01001896 }
1897 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1898 struct wordlist *it, *c;
1899
Remi Tricot-Le Bretond90aa342021-05-19 10:45:12 +02001900 /* get the info of the children in the env */
1901 if (mworker_env_to_proc_list() < 0) {
1902 exit(EXIT_FAILURE);
1903 }
William Lallemande7361152018-10-26 14:47:36 +02001904
William Lallemand550db6d2018-11-06 17:37:12 +01001905 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02001906
William Lallemand550db6d2018-11-06 17:37:12 +01001907 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02001908 ha_alert("Can't create the master's CLI.\n");
1909 exit(EXIT_FAILURE);
1910 }
William Lallemande7361152018-10-26 14:47:36 +02001911
William Lallemand550db6d2018-11-06 17:37:12 +01001912 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
1913
1914 if (mworker_cli_proxy_new_listener(c->s) < 0) {
1915 ha_alert("Can't create the master's CLI.\n");
1916 exit(EXIT_FAILURE);
1917 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001918 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01001919 free(c->s);
1920 free(c);
1921 }
1922 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001923 }
1924
Eric Salama5ba83352021-03-16 15:11:17 +01001925 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
1926 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
1927 }
1928
Willy Tarreauf42d7942020-10-20 11:54:49 +02001929 if (global.nbproc > 1 && !global.nbthread) {
1930 ha_warning("nbproc is deprecated!\n"
1931 " | For suffering many limitations, the 'nbproc' directive is now deprecated\n"
1932 " | and scheduled for removal in 2.5. Just comment it out: haproxy will use\n"
1933 " | threads and will run on all allocated processors. You may also switch to\n"
1934 " | 'nbthread %d' to keep the same number of processors. If you absolutely\n"
1935 " | want to run in multi-process mode, you can silence this warning by adding\n"
1936 " | 'nbthread 1', but then please report your use case to developers.\n",
1937 global.nbproc);
1938 }
1939
Willy Tarreaue90904d2021-02-12 14:08:31 +01001940 /* defaults sections are not needed anymore */
1941 proxy_destroy_all_defaults();
1942
Willy Tarreaubb925012009-07-23 13:36:36 +02001943 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02001944 for (px = proxies_list; px; px = px->next) {
1945 struct server *srv;
1946 struct post_proxy_check_fct *ppcf;
1947 struct post_server_check_fct *pscf;
1948
Christopher Fauletd5bd8242020-11-02 16:20:13 +01001949 if (px->disabled)
1950 continue;
1951
Christopher Fauletc1692962019-08-12 09:51:07 +02001952 list_for_each_entry(pscf, &post_server_check_list, list) {
1953 for (srv = px->srv; srv; srv = srv->next)
1954 err_code |= pscf->fct(srv);
1955 }
1956 list_for_each_entry(ppcf, &post_proxy_check_list, list)
1957 err_code |= ppcf->fct(px);
1958 }
Willy Tarreaubb925012009-07-23 13:36:36 +02001959 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001960 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001961 exit(1);
1962 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001963
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01001964 err_code |= pattern_finalize_config();
1965 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1966 ha_alert("Failed to finalize pattern config.\n");
1967 exit(1);
1968 }
Willy Tarreau0f936722019-04-11 14:47:08 +02001969
Willy Tarreau70060452015-12-14 12:46:07 +01001970 /* recompute the amount of per-process memory depending on nbproc and
1971 * the shared SSL cache size (allowed to exist in all processes).
1972 */
1973 if (global.rlimit_memmax_all) {
1974#if defined (USE_OPENSSL) && !defined(USE_PRIVATE_CACHE)
1975 int64_t ssl_cache_bytes = global.tune.sslcachesize * 200LL;
1976
1977 global.rlimit_memmax =
1978 ((((int64_t)global.rlimit_memmax_all * 1048576LL) -
1979 ssl_cache_bytes) / global.nbproc +
1980 ssl_cache_bytes + 1048575LL) / 1048576LL;
1981#else
1982 global.rlimit_memmax = global.rlimit_memmax_all / global.nbproc;
1983#endif
1984 }
1985
Willy Tarreaue5733232019-05-22 19:24:06 +02001986#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01001987 err_code |= netns_init();
1988 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001989 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01001990 exit(1);
1991 }
1992#endif
1993
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01001994 /* Apply server states */
1995 apply_server_state();
1996
Olivier Houchardfbc74e82017-11-24 16:54:05 +01001997 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01001998 srv_compute_all_admin_states(px);
1999
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002000 /* Apply servers' configured address */
2001 err_code |= srv_init_addr();
2002 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002003 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002004 exit(1);
2005 }
2006
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002007 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2008 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2009 exit(1);
2010 }
2011
Willy Tarreaubaaee002006-06-26 02:48:02 +02002012 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002013 struct peers *pr;
2014 struct proxy *px;
2015
Willy Tarreaubebd2122020-04-15 16:06:11 +02002016 if (warned & WARN_ANY)
2017 qfprintf(stdout, "Warnings were found.\n");
2018
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002019 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002020 if (pr->peers_fe)
2021 break;
2022
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002023 for (px = proxies_list; px; px = px->next)
Willy Tarreauc3914d42020-09-24 08:39:22 +02002024 if (!px->disabled && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002025 break;
2026
Emeric Brun3a9c0002021-08-13 09:32:50 +02002027 if (!px) {
2028 /* We may only have log-forward section */
2029 for (px = cfg_log_forward; px; px = px->next)
2030 if (!px->disabled && px->li_all)
2031 break;
2032 }
2033
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002034 if (pr || px) {
2035 /* At least one peer or one listener has been found */
2036 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002037 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002038 }
2039 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2040 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002041 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002042
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002043 if (global.mode & MODE_DIAG) {
2044 cfg_run_diagnostics();
2045 }
2046
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002047 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002048 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002049
Willy Tarreaue6945732016-12-21 19:57:00 +01002050 list_for_each_entry(pcf, &post_check_list, list) {
2051 err_code |= pcf->fct();
2052 if (err_code & (ERR_ABORT|ERR_FATAL))
2053 exit(1);
2054 }
2055
Willy Tarreaubaaee002006-06-26 02:48:02 +02002056 if (cfg_maxconn > 0)
2057 global.maxconn = cfg_maxconn;
2058
Willy Tarreau4975d142021-03-13 11:00:33 +01002059 if (global.cli_fe)
2060 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002061
2062 if (cfg_peers) {
2063 /* peers also need to bypass global maxconn */
2064 struct peers *p = cfg_peers;
2065
2066 for (p = cfg_peers; p; p = p->next)
2067 if (p->peers_fe)
2068 global.maxsock += p->peers_fe->maxconn;
2069 }
2070
Willy Tarreaubaaee002006-06-26 02:48:02 +02002071 if (cfg_pidfile) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002072 free(global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073 global.pidfile = strdup(cfg_pidfile);
2074 }
2075
Willy Tarreaud0256482015-01-15 21:45:22 +01002076 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002077 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2078 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2079 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2080 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002081 *
2082 * If memmax is set, then it depends on which values are set. If
2083 * maxsslconn is set, we use memmax to determine how many cleartext
2084 * connections may be added, and set maxconn to the sum of the two.
2085 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2086 * the remaining amount of memory between memmax and the cleartext
2087 * connections. If neither are set, then it is considered that all
2088 * connections are SSL-capable, and maxconn is computed based on this,
2089 * then maxsslconn accordingly. We need to know if SSL is used on the
2090 * frontends, backends, or both, because when it's used on both sides,
2091 * we need twice the value for maxsslconn, but we only count the
2092 * handshake once since it is not performed on the two sides at the
2093 * same time (frontend-side is terminated before backend-side begins).
2094 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002095 * ssl_handshake_cost during its initialization. In any case, if
2096 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2097 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002098 */
Willy Tarreauac350932019-03-01 15:43:14 +01002099 ideal_maxconn = compute_ideal_maxconn();
2100
Willy Tarreaud0256482015-01-15 21:45:22 +01002101 if (!global.rlimit_memmax) {
2102 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002103 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002104 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2105 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2106 }
2107 }
2108#ifdef USE_OPENSSL
2109 else if (!global.maxconn && !global.maxsslconn &&
2110 (global.ssl_used_frontend || global.ssl_used_backend)) {
2111 /* memmax is set, compute everything automatically. Here we want
2112 * to ensure that all SSL connections will be served. We take
2113 * care of the number of sides where SSL is used, and consider
2114 * the worst case : SSL used on both sides and doing a handshake
2115 * simultaneously. Note that we can't have more than maxconn
2116 * handshakes at a time by definition, so for the worst case of
2117 * two SSL conns per connection, we count a single handshake.
2118 */
2119 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2120 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002121 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002122
2123 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2124 mem -= global.maxzlibmem;
2125 mem = mem * MEM_USABLE_RATIO;
2126
Willy Tarreau304e17e2020-03-10 17:54:54 +01002127 /* Principle: we test once to set maxconn according to the free
2128 * memory. If it results in values the system rejects, we try a
2129 * second time by respecting rlim_fd_max. If it fails again, we
2130 * go back to the initial value and will let the final code
2131 * dealing with rlimit report the error. That's up to 3 attempts.
2132 */
2133 do {
2134 global.maxconn = mem /
2135 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2136 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2137 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002138
Willy Tarreau304e17e2020-03-10 17:54:54 +01002139 if (retried == 1)
2140 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2141 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002142#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002143 if (global.maxconn > SYSTEM_MAXCONN)
2144 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002145#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002146 global.maxsslconn = sides * global.maxconn;
2147
2148 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2149 break;
2150 } while (retried++ < 2);
2151
Willy Tarreaud0256482015-01-15 21:45:22 +01002152 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2153 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2154 global.maxconn, global.maxsslconn);
2155 }
2156 else if (!global.maxsslconn &&
2157 (global.ssl_used_frontend || global.ssl_used_backend)) {
2158 /* memmax and maxconn are known, compute maxsslconn automatically.
2159 * maxsslconn being forced, we don't know how many of it will be
2160 * on each side if both sides are being used. The worst case is
2161 * when all connections use only one SSL instance because
2162 * handshakes may be on two sides at the same time.
2163 */
2164 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2165 int64_t mem = global.rlimit_memmax * 1048576ULL;
2166 int64_t sslmem;
2167
2168 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2169 mem -= global.maxzlibmem;
2170 mem = mem * MEM_USABLE_RATIO;
2171
Willy Tarreau87b09662015-04-03 00:22:06 +02002172 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002173 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2174 global.maxsslconn = round_2dig(global.maxsslconn);
2175
2176 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002177 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2178 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2179 "without SSL is %d, but %d was found and SSL is in use.\n",
2180 global.rlimit_memmax,
2181 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2182 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002183 exit(1);
2184 }
2185
2186 if (global.maxsslconn > sides * global.maxconn)
2187 global.maxsslconn = sides * global.maxconn;
2188
2189 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2190 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2191 }
2192#endif
2193 else if (!global.maxconn) {
2194 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2195 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2196 int64_t mem = global.rlimit_memmax * 1048576ULL;
2197 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002198 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002199
2200 if (global.ssl_used_frontend || global.ssl_used_backend)
2201 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2202
2203 mem -= global.maxzlibmem;
2204 mem = mem * MEM_USABLE_RATIO;
2205
2206 clearmem = mem;
2207 if (sides)
2208 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2209
Willy Tarreau304e17e2020-03-10 17:54:54 +01002210 /* Principle: we test once to set maxconn according to the free
2211 * memory. If it results in values the system rejects, we try a
2212 * second time by respecting rlim_fd_max. If it fails again, we
2213 * go back to the initial value and will let the final code
2214 * dealing with rlimit report the error. That's up to 3 attempts.
2215 */
2216 do {
2217 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2218 if (retried == 1)
2219 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2220 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002221#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002222 if (global.maxconn > SYSTEM_MAXCONN)
2223 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002224#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002225
Willy Tarreau304e17e2020-03-10 17:54:54 +01002226 if (clearmem <= 0 || !global.maxconn) {
2227 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2228 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2229 "is %d, but %d was found.\n",
2230 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002231 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002232 global.maxsslconn);
2233 exit(1);
2234 }
2235
2236 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2237 break;
2238 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002239
2240 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2241 if (sides && global.maxsslconn > sides * global.maxconn) {
2242 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2243 "to be limited to %d. Better reduce global.maxsslconn to get more "
2244 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2245 }
2246 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2247 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002248 }
2249
Willy Tarreaua409f302020-03-10 17:08:53 +01002250 global.maxsock = compute_ideal_maxsock(global.maxconn);
2251 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002252 if (!global.maxpipes)
2253 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254
Olivier Houchard88698d92019-04-16 19:07:22 +02002255 /* update connection pool thresholds */
2256 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2257 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2258
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002259 proxy_adjust_all_maxconn();
2260
Willy Tarreau1db37712007-06-03 17:16:49 +02002261 if (global.tune.maxpollevents <= 0)
2262 global.tune.maxpollevents = MAX_POLL_EVENTS;
2263
Willy Tarreau060a7612021-03-10 11:06:26 +01002264 if (global.tune.runqueue_depth <= 0) {
2265 /* tests on various thread counts from 1 to 64 have shown an
2266 * optimal queue depth following roughly 1/sqrt(threads).
2267 */
2268 int s = my_flsl(global.nbthread);
2269 s += (global.nbthread / s); // roughly twice the sqrt.
2270 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2271 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002272
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002273 if (global.tune.recv_enough == 0)
2274 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2275
Willy Tarreau27a674e2009-08-17 07:23:33 +02002276 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2277 global.tune.maxrewrite = global.tune.bufsize / 2;
2278
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2280 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002281 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002282 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2283 }
2284
William Lallemand095ba4c2017-06-01 17:38:50 +02002285 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002286 /* command line daemon mode inhibits foreground and debug modes mode */
2287 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002288 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002289 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002290
2291 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292
William Lallemand095ba4c2017-06-01 17:38:50 +02002293 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002294 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002295 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 }
2297
William Lallemand095ba4c2017-06-01 17:38:50 +02002298 if ((global.nbproc > 1) && !(global.mode & (MODE_DAEMON | MODE_MWORKER))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 if (!(global.mode & (MODE_FOREGROUND | MODE_DEBUG)))
Christopher Faulet767a84b2017-11-24 16:50:31 +01002300 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 +02002301 global.nbproc = 1;
2302 }
2303
2304 if (global.nbproc < 1)
2305 global.nbproc = 1;
2306
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002307 if (global.nbthread < 1)
2308 global.nbthread = 1;
2309
Christopher Faulet3ef26392017-08-29 16:46:57 +02002310 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002311 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002312 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002313 exit(1);
2314 }
2315
Christopher Faulet96d44832017-11-14 22:02:30 +01002316 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002317 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002318 exit(1);
2319 }
2320
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002321 /*
2322 * Note: we could register external pollers here.
2323 * Built-in pollers have been registered before main().
2324 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002325
Willy Tarreau43b78992009-01-25 15:42:27 +01002326 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002327 disable_poller("kqueue");
2328
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002329 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2330 disable_poller("evports");
2331
Willy Tarreau43b78992009-01-25 15:42:27 +01002332 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002333 disable_poller("epoll");
2334
Willy Tarreau43b78992009-01-25 15:42:27 +01002335 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002336 disable_poller("poll");
2337
Willy Tarreau43b78992009-01-25 15:42:27 +01002338 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002339 disable_poller("select");
2340
2341 /* Note: we could disable any poller by name here */
2342
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002343 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002344 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002345 fprintf(stderr, "\n");
2346 list_filters(stderr);
2347 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002348
Willy Tarreau4f60f162007-04-08 16:39:58 +02002349 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002350 ha_alert("No polling mechanism available.\n"
2351 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2352 " is too low on this platform to support maxconn and the number of listeners\n"
2353 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2354 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2355 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2356 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2357 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2358 " check build settings using 'haproxy -vv'.\n\n",
2359 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002360 exit(1);
2361 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002362 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2363 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002364 }
2365
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002366 if (!global.node)
2367 global.node = strdup(hostname);
2368
Willy Tarreau02b092f2020-10-07 18:36:54 +02002369 /* stop disabled proxies */
2370 for (px = proxies_list; px; px = px->next) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02002371 if (px->disabled)
Willy Tarreau02b092f2020-10-07 18:36:54 +02002372 stop_proxy(px);
2373 }
2374
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002375 if (!hlua_post_init())
2376 exit(1);
Thomas Holmes6abded42015-05-12 16:23:58 +01002377
Maxime de Roucy0f503922016-05-13 23:52:55 +02002378 free(err_msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379}
2380
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002381void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002383 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002384 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002385 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002386 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002387 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002388 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002389 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002390 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002391 struct per_thread_init_fct *tif, *tifb;
2392 struct per_thread_deinit_fct *tdf, *tdfb;
2393 struct per_thread_alloc_fct *taf, *tafb;
2394 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002395 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002396 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002397 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002398 int cur_fd;
2399
2400 /* At this point the listeners state is weird:
2401 * - most listeners are still bound and referenced in their protocol
2402 * - some might be zombies that are not in their proto anymore, but
2403 * still appear in their proxy's listeners with a valid FD.
2404 * - some might be stopped and still appear in their proxy as FD #-1
2405 * - among all of them, some might be inherited hence shared and we're
2406 * not allowed to pause them or whatever, we must just close them.
2407 * - finally some are not listeners (pipes, logs, stdout, etc) and
2408 * must be left intact.
2409 *
2410 * The safe way to proceed is to unbind (and close) whatever is not yet
2411 * unbound so that no more receiver/listener remains alive. Then close
2412 * remaining listener FDs, which correspond to zombie listeners (those
2413 * belonging to disabled proxies that were in another process).
2414 * objt_listener() would be cleaner here but not converted yet.
2415 */
2416 protocol_unbind_all();
2417
2418 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002419 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002420 continue;
2421
Willy Tarreaua74cb382020-10-15 21:29:49 +02002422 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002423 struct listener *l = fdtab[cur_fd].owner;
2424
2425 BUG_ON(l->state != LI_INIT);
2426 unbind_listener(l);
2427 }
2428 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002429
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002430 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002431 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002432 /* build a list of unique uri_auths */
2433 if (!ua)
2434 ua = p->uri_auth;
2435 else {
2436 /* check if p->uri_auth is unique */
2437 for (uap = ua; uap; uap=uap->next)
2438 if (uap == p->uri_auth)
2439 break;
2440
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002441 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002442 /* add it, if it is */
2443 p->uri_auth->next = ua;
2444 ua = p->uri_auth;
2445 }
William Lallemand0f99e342011-10-12 17:50:54 +02002446 }
2447
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002448 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002450 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002452
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002453 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002454 struct stat_scope *scope, *scopep;
2455
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002456 uap = ua;
2457 ua = ua->next;
2458
Willy Tarreaua534fea2008-08-03 12:19:50 +02002459 free(uap->uri_prefix);
2460 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002461 free(uap->node);
2462 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002463
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002464 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002465 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002466
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002467 scope = uap->scope;
2468 while (scope) {
2469 scopep = scope;
2470 scope = scope->next;
2471
2472 free(scopep->px_id);
2473 free(scopep);
2474 }
2475
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002476 free(uap);
2477 }
2478
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002479 userlist_free(userlist);
2480
David Carlier834cb2e2015-09-25 12:02:25 +01002481 cfg_unregister_sections();
2482
Christopher Faulet0132d062017-07-26 15:33:35 +02002483 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002484
Willy Tarreau05554e62016-12-21 20:46:26 +01002485 list_for_each_entry(pdf, &post_deinit_list, list)
2486 pdf->fct();
2487
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002488 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002489 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002490 ha_free(&global.chroot);
2491 ha_free(&global.pidfile);
2492 ha_free(&global.node);
2493 ha_free(&global.desc);
2494 ha_free(&oldpids);
2495 ha_free(&old_argv);
2496 ha_free(&localpeer);
2497 ha_free(&global.server_state_base);
2498 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002499 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002500 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002501
William Lallemand0f99e342011-10-12 17:50:54 +02002502 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002503 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002504 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002505 free(log);
2506 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002507 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002508 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002509 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002510 free(wl);
2511 }
2512
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002513 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2514 if (bol->must_free)
2515 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002516 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002517 free(bol);
2518 }
2519
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002520 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002521 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002522 free(pxdf);
2523 }
2524
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002525 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002526 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002527 free(pdf);
2528 }
2529
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002530 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002531 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002532 free(srvdf);
2533 }
2534
Tim Duesterhusfc854942020-09-10 19:46:42 +02002535 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002536 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002537 free(pcf);
2538 }
2539
Tim Duesterhus34bef072020-07-04 11:49:50 +02002540 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002541 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002542 free(pscf);
2543 }
2544
Tim Duesterhus53508d62020-09-10 19:46:40 +02002545 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002546 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002547 free(ppcf);
2548 }
2549
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002550 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002551 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002552 free(tif);
2553 }
2554
2555 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002556 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002557 free(tdf);
2558 }
2559
2560 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002561 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002562 free(taf);
2563 }
2564
2565 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002566 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002567 free(tff);
2568 }
2569
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002570 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002571 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002572 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573} /* end deinit() */
2574
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002575__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002576{
Amaury Denoyelle890f4be2021-08-09 15:02:56 +02002577 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002578 deinit();
2579 exit(status);
2580}
William Lallemand72160322018-11-06 17:37:16 +01002581
Willy Tarreau918ff602011-07-25 16:33:49 +02002582/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002583void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002584{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002585 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002586
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002587 tv_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002588 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002589 wake_expired_tasks();
2590
William Lallemand1aab50b2018-06-07 09:46:01 +02002591 /* check if we caught some signals and process them in the
2592 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002593 if (signal_queue_len && tid == 0) {
2594 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002595 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002596 }
2597
2598 /* Process a few tasks */
2599 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002600
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002601 /* also stop if we failed to cleanly stop all tasks */
2602 if (killed > 1)
2603 break;
2604
Willy Tarreau10146c92015-04-13 20:44:19 +02002605 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002606 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002607 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002608 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002609 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002610 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2611 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002612 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002613 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002614 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002615 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002616 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002617 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002618
Willy Tarreau4f46a352020-03-23 09:27:28 +01002619 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002620 int i;
2621
2622 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002623 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002624 if (!(stopping_thread_mask & tid_bit)) {
2625 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2626 wake = 1;
2627 }
2628
Willy Tarreau1db42732021-04-06 11:44:07 +02002629 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002630 /* notify all threads that stopping was just set */
2631 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002632 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002633 wake_thread(i);
2634 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002635 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002636
2637 /* stop when there's nothing left to do */
2638 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002639 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2640 /* wake all threads waiting on jobs==0 */
2641 for (i = 0; i < global.nbthread; i++)
2642 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2643 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002644 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002645 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002646 }
2647
Willy Tarreauc49ba522019-12-11 08:12:23 +01002648 /* If we have to sleep, measure how long */
2649 next = wake ? TICK_ETERNITY : next_timer_expiry();
2650
Willy Tarreau58b458d2008-06-29 22:40:23 +02002651 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002652 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002653
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002654 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002655 }
2656}
2657
Christopher Faulet1d17c102017-08-29 15:38:48 +02002658static void *run_thread_poll_loop(void *data)
2659{
Willy Tarreau082b6282019-05-22 14:42:12 +02002660 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002661 struct per_thread_init_fct *ptif;
2662 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002663 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002664 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002665 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2666 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002667
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02002668 ha_set_tid((unsigned long)data);
Willy Tarreaud022e9c2019-09-24 08:25:15 +02002669 sched = &task_per_thread[tid];
Willy Tarreau91e6df02019-05-03 17:21:18 +02002670
Willy Tarreauf6178242019-05-21 19:46:58 +02002671#if (_POSIX_TIMERS > 0) && defined(_POSIX_THREAD_CPUTIME)
Willy Tarreau91e6df02019-05-03 17:21:18 +02002672#ifdef USE_THREAD
Willy Tarreau8323a372019-05-20 18:57:53 +02002673 pthread_getcpuclockid(pthread_self(), &ti->clock_id);
Willy Tarreau624dcbf2019-05-20 20:23:06 +02002674#else
Willy Tarreau8323a372019-05-20 18:57:53 +02002675 ti->clock_id = CLOCK_THREAD_CPUTIME_ID;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002676#endif
Willy Tarreau663fda42019-05-21 15:14:08 +02002677#endif
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002678 /* Now, initialize one thread init at a time. This is better since
2679 * some init code is a bit tricky and may release global resources
2680 * after reallocating them locally. This will also ensure there is
2681 * no race on file descriptors allocation.
2682 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002683#ifdef USE_THREAD
2684 pthread_mutex_lock(&init_mutex);
2685#endif
2686 /* The first thread must set the number of threads left */
2687 if (!init_left)
2688 init_left = global.nbthread;
2689 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002690
Willy Tarreauc4c80fb2021-04-11 15:00:34 +02002691 tv_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002692
Willy Tarreau082b6282019-05-22 14:42:12 +02002693 /* per-thread alloc calls performed here are not allowed to snoop on
2694 * other threads, so they are free to initialize at their own rhythm
2695 * as long as they act as if they were alone. None of them may rely
2696 * on resources initialized by the other ones.
2697 */
2698 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2699 if (!ptaf->fct()) {
2700 ha_alert("failed to allocate resources for thread %u.\n", tid);
2701 exit(1);
2702 }
2703 }
2704
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002705 /* per-thread init calls performed here are not allowed to snoop on
2706 * other threads, so they are free to initialize at their own rhythm
2707 * as long as they act as if they were alone.
2708 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002709 list_for_each_entry(ptif, &per_thread_init_list, list) {
2710 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002711 ha_alert("failed to initialize thread %u.\n", tid);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002712 exit(1);
2713 }
2714 }
2715
Willy Tarreau71092822019-06-10 09:51:04 +02002716 /* enabling protocols will result in fd_insert() calls to be performed,
2717 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002718 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002719 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002720 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002721 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002722
Willy Tarreau34a150c2019-06-11 09:16:41 +02002723#ifdef USE_THREAD
2724 pthread_cond_broadcast(&init_cond);
2725 pthread_mutex_unlock(&init_mutex);
2726
2727 /* now wait for other threads to finish starting */
2728 pthread_mutex_lock(&init_mutex);
2729 while (init_left)
2730 pthread_cond_wait(&init_cond, &init_mutex);
2731 pthread_mutex_unlock(&init_mutex);
2732#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002733
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002734#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2735 /* Let's refrain from using setuid executables. This way the impact of
2736 * an eventual vulnerability in a library remains limited. It may
2737 * impact external checks but who cares about them anyway ? In the
2738 * worst case it's possible to disable the option. Obviously we do this
2739 * in workers only. We can't hard-fail on this one as it really is
2740 * implementation dependent though we're interested in feedback, hence
2741 * the warning.
2742 */
2743 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2744 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002745 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 +01002746 ha_warning("Failed to disable setuid, please report to developers with detailed "
2747 "information about your operating system. You can silence this warning "
2748 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2749 }
2750 }
2751#endif
2752
Willy Tarreaud96f1122019-12-03 07:07:36 +01002753#if defined(RLIMIT_NPROC)
2754 /* all threads have started, it's now time to prevent any new thread
2755 * or process from starting. Obviously we do this in workers only. We
2756 * can't hard-fail on this one as it really is implementation dependent
2757 * though we're interested in feedback, hence the warning.
2758 */
2759 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2760 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2761 static int warn_fail;
2762
Willy Tarreau18515722021-04-06 11:57:41 +02002763 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002764 ha_warning("Failed to disable forks, please report to developers with detailed "
2765 "information about your operating system. You can silence this warning "
2766 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2767 }
2768 }
2769#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002770 run_poll_loop();
2771
2772 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2773 ptdf->fct();
2774
Willy Tarreau082b6282019-05-22 14:42:12 +02002775 list_for_each_entry(ptff, &per_thread_free_list, list)
2776 ptff->fct();
2777
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002778#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002779 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002780 if (tid > 0)
2781 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002782#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002783 return NULL;
2784}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002785
William Dauchyf9af9d72019-11-17 15:47:16 +01002786/* set uid/gid depending on global settings */
2787static void set_identity(const char *program_name)
2788{
2789 if (global.gid) {
2790 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2791 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2792 " without 'uid'/'user' is generally useless.\n", program_name);
2793
2794 if (setgid(global.gid) == -1) {
2795 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2796 protocol_unbind_all();
2797 exit(1);
2798 }
2799 }
2800
2801 if (global.uid && setuid(global.uid) == -1) {
2802 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2803 protocol_unbind_all();
2804 exit(1);
2805 }
2806}
2807
Willy Tarreaubaaee002006-06-26 02:48:02 +02002808int main(int argc, char **argv)
2809{
2810 int err, retry;
2811 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002812 int pidfd = -1;
Willy Tarreau08293ed2021-07-14 17:54:01 +02002813 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2814
2815 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2816 if (intovf + 0x7FFFFFFF >= intovf) {
2817 fprintf(stderr,
2818 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2819 "The source code was miscompiled by the compiler, which usually indicates that\n"
2820 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2821 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2822 "and INSTALL files to decide on the best way to pass your local build options.\n"
2823 "\nBuild options :"
2824#ifdef BUILD_TARGET
2825 "\n TARGET = " BUILD_TARGET
2826#endif
2827#ifdef BUILD_CPU
2828 "\n CPU = " BUILD_CPU
2829#endif
2830#ifdef BUILD_CC
2831 "\n CC = " BUILD_CC
2832#endif
2833#ifdef BUILD_CFLAGS
2834 "\n CFLAGS = " BUILD_CFLAGS
2835#endif
2836#ifdef BUILD_OPTIONS
2837 "\n OPTIONS = " BUILD_OPTIONS
2838#endif
2839#ifdef BUILD_DEBUG
2840 "\n DEBUG = " BUILD_DEBUG
2841#endif
2842 "\n\n");
2843 return 1;
2844 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002846 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002847
Willy Tarreauff9c9142019-02-07 10:39:36 +01002848 /* this can only safely be done here, though it's optimized away by
2849 * the compiler.
2850 */
2851 if (MAX_PROCS < 1 || MAX_PROCS > LONGBITS) {
2852 ha_alert("MAX_PROCS value must be between 1 and %d inclusive; "
2853 "HAProxy was built with value %d, please fix it and rebuild.\n",
2854 LONGBITS, MAX_PROCS);
2855 exit(1);
2856 }
2857
Willy Tarreaubf696402019-03-01 10:09:28 +01002858 /* take a copy of initial limits before we possibly change them */
2859 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02002860
2861 if (limit.rlim_max == RLIM_INFINITY)
2862 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01002863 rlim_fd_cur_at_boot = limit.rlim_cur;
2864 rlim_fd_max_at_boot = limit.rlim_max;
2865
Willy Tarreau5794fb02018-11-25 18:43:29 +01002866 /* process all initcalls in order of potential dependency */
2867 RUN_INITCALLS(STG_PREPARE);
2868 RUN_INITCALLS(STG_LOCK);
2869 RUN_INITCALLS(STG_ALLOC);
2870 RUN_INITCALLS(STG_POOL);
2871 RUN_INITCALLS(STG_REGISTER);
2872 RUN_INITCALLS(STG_INIT);
2873
Emeric Bruncf20bf12010-10-22 16:06:11 +02002874 init(argc, argv);
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002875 signal_register_fct(SIGQUIT, dump, SIGQUIT);
2876 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
2877 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02002878 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879
Willy Tarreaue437c442010-03-17 18:02:46 +01002880 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
2881 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
2882 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002884 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885
Willy Tarreaudc23a922011-02-16 11:10:36 +01002886 /* ulimits */
2887 if (!global.rlimit_nofile)
2888 global.rlimit_nofile = global.maxsock;
2889
2890 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01002891 limit.rlim_cur = global.rlimit_nofile;
2892 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
2893
Willy Tarreaudc23a922011-02-16 11:10:36 +01002894 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02002895 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002896 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2897 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
2898 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002899 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002900 }
2901 else {
2902 /* try to set it to the max possible at least */
2903 limit.rlim_cur = limit.rlim_max;
2904 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
2905 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02002906
William Dauchya5194602020-03-28 19:29:58 +01002907 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002908 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
2909 global.rlimit_nofile = limit.rlim_cur;
2910 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01002911 }
2912 }
2913
2914 if (global.rlimit_memmax) {
2915 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01002916 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01002917#ifdef RLIMIT_AS
2918 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002919 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2920 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2921 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002922 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002923 }
2924 else
William Dauchya5194602020-03-28 19:29:58 +01002925 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002926 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002927 }
2928#else
2929 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002930 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2931 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2932 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002933 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002934 }
2935 else
William Dauchya5194602020-03-28 19:29:58 +01002936 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002937 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002938 }
2939#endif
2940 }
2941
Olivier Houchardf73629d2017-04-05 22:33:04 +02002942 if (old_unixsocket) {
William Lallemand85b0bd92017-06-01 17:38:53 +02002943 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02002944 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002945 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02002946 if (!(global.mode & MODE_MWORKER))
2947 exit(1);
2948 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02002949 }
2950 }
William Lallemand85b0bd92017-06-01 17:38:53 +02002951 get_cur_unixsocket();
2952
Willy Tarreaubaaee002006-06-26 02:48:02 +02002953 /* We will loop at most 100 times with 10 ms delay each time.
2954 * That's at most 1 second. We only send a signal to old pids
2955 * if we cannot grab at least one port.
2956 */
2957 retry = MAX_START_RETRIES;
2958 err = ERR_NONE;
2959 while (retry >= 0) {
2960 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02002961 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01002962 /* exit the loop on no error or fatal error */
2963 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002964 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02002965 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 break;
2967
2968 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
2969 * listening sockets. So on those platforms, it would be wiser to
2970 * simply send SIGUSR1, which will not be undoable.
2971 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02002972 if (tell_old_pids(SIGTTOU) == 0) {
2973 /* no need to wait if we can't contact old pids */
2974 retry = 0;
2975 continue;
2976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002977 /* give some time to old processes to stop listening */
2978 w.tv_sec = 0;
2979 w.tv_usec = 10*1000;
2980 select(0, NULL, NULL, NULL, &w);
2981 retry--;
2982 }
2983
Willy Tarreaue91bff22020-09-02 11:11:43 +02002984 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01002985 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02002986 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02002987 if (retry != MAX_START_RETRIES && nb_oldpids) {
2988 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002989 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02002990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 exit(1);
2992 }
2993
William Lallemand944e6192018-11-21 15:48:31 +01002994 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002995 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002996 /* Note: we don't have to send anything to the old pids because we
2997 * never stopped them. */
2998 exit(1);
2999 }
3000
Willy Tarreaue91bff22020-09-02 11:11:43 +02003001 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003002 * the previous process gave us, we don't need them anymore
3003 */
3004 while (xfer_sock_list != NULL) {
3005 struct xfer_sock_list *tmpxfer = xfer_sock_list->next;
3006 close(xfer_sock_list->fd);
3007 free(xfer_sock_list->iface);
3008 free(xfer_sock_list->namespace);
3009 free(xfer_sock_list);
3010 xfer_sock_list = tmpxfer;
3011 }
Willy Tarreaudd815982007-10-16 12:25:14 +02003012
Willy Tarreaubaaee002006-06-26 02:48:02 +02003013 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003014 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3015 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016
Willy Tarreaubaaee002006-06-26 02:48:02 +02003017 /* MODE_QUIET can inhibit alerts and warnings below this line */
3018
PiBa-NL149a81a2017-12-25 21:03:31 +01003019 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3020 /* either stdin/out/err are already closed or should stay as they are. */
3021 if ((global.mode & MODE_DAEMON)) {
3022 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3023 global.mode &= ~MODE_VERBOSE;
3024 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3025 }
3026 } else {
3027 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3028 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003029 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003030 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031 }
3032
3033 /* open log & pid files before the chroot */
William Lallemand80293002017-11-06 11:00:03 +01003034 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003035 unlink(global.pidfile);
3036 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3037 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003038 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 if (nb_oldpids)
3040 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003041 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042 exit(1);
3043 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044 }
3045
Willy Tarreaub38651a2007-03-24 17:24:39 +01003046 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003047 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3048 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003049 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003050 exit(1);
3051 }
3052
Jackie Tapia749f74c2020-07-22 18:59:40 -05003053 /* If the user is not root, we'll still let them try the configuration
3054 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003055 */
3056 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003057 ha_warning("[%s.main()] Some options which require full privileges"
3058 " might not work well.\n"
3059 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003060
William Lallemand095ba4c2017-06-01 17:38:50 +02003061 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3062
3063 /* chroot if needed */
3064 if (global.chroot != NULL) {
3065 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003066 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003067 if (nb_oldpids)
3068 tell_old_pids(SIGTTIN);
3069 protocol_unbind_all();
3070 exit(1);
3071 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003072 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003073 }
3074
William Lallemand944e6192018-11-21 15:48:31 +01003075 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003076 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077
William Lallemand27edc4b2019-05-07 17:49:33 +02003078 /* send a SIGTERM to workers who have a too high reloads number */
3079 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3080 mworker_kill_max_reloads(SIGTERM);
3081
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 /* Note that any error at this stage will be fatal because we will not
3083 * be able to restart the old pids.
3084 */
3085
William Dauchyf9af9d72019-11-17 15:47:16 +01003086 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3087 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003088
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 /* check ulimits */
3090 limit.rlim_cur = limit.rlim_max = 0;
3091 getrlimit(RLIMIT_NOFILE, &limit);
3092 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003093 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3094 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3095 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3096 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3097 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003098 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003099 }
3100 else
3101 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003102 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003103 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3104 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 }
3106
William Lallemand944e6192018-11-21 15:48:31 +01003107 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003108 struct proxy *px;
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003109 struct peers *curpeers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 int ret = 0;
3111 int proc;
William Lallemande1340412017-12-28 16:09:36 +01003112 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113
William Lallemand095ba4c2017-06-01 17:38:50 +02003114 /*
3115 * if daemon + mworker: must fork here to let a master
3116 * process live in background before forking children
3117 */
William Lallemand73b85e72017-06-01 17:38:51 +02003118
3119 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3120 && (global.mode & MODE_MWORKER)
3121 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003122 ret = fork();
3123 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003124 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003125 protocol_unbind_all();
3126 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003127 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003128 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003129 } else /* change the process group ID in the child (master process) */
3130 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003131 }
William Lallemande20b6a62017-06-01 17:38:55 +02003132
William Lallemande20b6a62017-06-01 17:38:55 +02003133
William Lallemanddeed7802017-11-06 11:00:04 +01003134 /* if in master-worker mode, write the PID of the father */
3135 if (global.mode & MODE_MWORKER) {
3136 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003137 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003138 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003139 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003140 }
3141
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003143 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003144 if (global.mode & MODE_MWORKER)
3145 mworker_ext_launch_all();
William Lallemand944e6192018-11-21 15:48:31 +01003146 for (proc = 0; proc < global.nbproc; proc++) {
3147 ret = fork();
3148 if (ret < 0) {
3149 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3150 protocol_unbind_all();
3151 exit(1); /* there has been an error */
3152 }
Willy Tarreau52bf8392020-03-08 00:42:37 +01003153 else if (ret == 0) { /* child breaks here */
Willy Tarreaua9274a12021-07-21 10:17:02 +02003154 /* This one must not be exported, it's internal! */
3155 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreau52bf8392020-03-08 00:42:37 +01003156 ha_random_jump96(relative_pid);
William Lallemand944e6192018-11-21 15:48:31 +01003157 break;
Willy Tarreau52bf8392020-03-08 00:42:37 +01003158 }
William Lallemand944e6192018-11-21 15:48:31 +01003159 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3160 char pidstr[100];
3161 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003162 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003163 }
3164 if (global.mode & MODE_MWORKER) {
3165 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003166
William Lallemand220567e2018-11-21 18:04:53 +01003167 ha_notice("New worker #%d (%d) forked\n", relative_pid, ret);
William Lallemand944e6192018-11-21 15:48:31 +01003168 /* find the right mworker_proc */
3169 list_for_each_entry(child, &proc_list, list) {
3170 if (child->relative_pid == relative_pid &&
William Lallemand8f7069a2019-04-12 16:09:23 +02003171 child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003172 child->timestamp = now.tv_sec;
3173 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003174 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003175 break;
3176 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003177 }
3178 }
William Lallemandbc193052018-09-11 10:06:26 +02003179
William Lallemand944e6192018-11-21 15:48:31 +01003180 relative_pid++; /* each child will get a different one */
3181 pid_bit <<= 1;
3182 }
3183 } else {
3184 /* wait mode */
3185 global.nbproc = 1;
3186 proc = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003188
3189#ifdef USE_CPU_AFFINITY
3190 if (proc < global.nbproc && /* child */
Willy Tarreauff9c9142019-02-07 10:39:36 +01003191 proc < MAX_PROCS && /* only the first 32/64 processes may be pinned */
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003192 ha_cpuset_count(&cpu_map.proc[proc])) { /* only do this if the process has a CPU map */
Olivier Houchard97148f62017-08-16 17:29:11 +02003193
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003194#ifdef __FreeBSD__
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003195 struct hap_cpuset *set = &cpu_map.proc[proc];
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003196 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
David Carlier2d0493a2020-12-02 21:14:51 +00003197#elif defined(__linux__) || defined(__DragonFly__)
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003198 struct hap_cpuset *set = &cpu_map.proc[proc];
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003199 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003200#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003201 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003202#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003204 if (pidfd >= 0) {
3205 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3206 close(pidfd);
3207 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003208
3209 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003210 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003212 if (proc == global.nbproc) {
William Lallemand944e6192018-11-21 15:48:31 +01003213 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003214
3215 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3216 (global.mode & MODE_DAEMON)) {
3217 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003218 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3219 stdio_quiet(-1);
3220
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003221 global.mode &= ~MODE_VERBOSE;
3222 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003223 }
3224
William Lallemandb3f2be32018-09-11 10:06:18 +02003225 mworker_loop();
William Lallemand1499b9b2017-06-07 15:04:47 +02003226 /* should never get there */
3227 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003228 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003229#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003230 ssl_free_dh();
3231#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003232 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003233 }
3234
William Lallemandcb11fd22017-06-01 17:38:52 +02003235 /* child must never use the atexit function */
3236 atexit_flag = 0;
3237
William Lallemandbc193052018-09-11 10:06:26 +02003238 /* close useless master sockets */
3239 if (global.mode & MODE_MWORKER) {
3240 struct mworker_proc *child, *it;
3241 master = 0;
3242
William Lallemand309dc9a2018-10-26 14:47:45 +02003243 mworker_cli_proxy_stop();
3244
William Lallemandbc193052018-09-11 10:06:26 +02003245 /* free proc struct of other processes */
3246 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003247 /* close the FD of the master side for all
3248 * workers, we don't need to close the worker
3249 * side of other workers since it's done with
3250 * the bind_proc */
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003251 if (child->ipc_fd[0] >= 0)
3252 close(child->ipc_fd[0]);
William Lallemandce83b4a2018-10-26 14:47:30 +02003253 if (child->relative_pid == relative_pid &&
3254 child->reloads == 0) {
3255 /* keep this struct if this is our pid */
3256 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003257 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003258 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003259 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003260 mworker_free_child(child);
3261 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003262 }
3263 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003264
William Lallemande1340412017-12-28 16:09:36 +01003265 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3266 devnullfd = open("/dev/null", O_RDWR, 0);
3267 if (devnullfd < 0) {
3268 ha_alert("Cannot open /dev/null\n");
3269 exit(EXIT_FAILURE);
3270 }
3271 }
3272
William Lallemand095ba4c2017-06-01 17:38:50 +02003273 /* Must chroot and setgid/setuid in the children */
3274 /* chroot if needed */
3275 if (global.chroot != NULL) {
3276 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreau46317372021-06-15 08:59:19 +02003277 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003278 if (nb_oldpids)
3279 tell_old_pids(SIGTTIN);
3280 protocol_unbind_all();
3281 exit(1);
3282 }
3283 }
3284
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003285 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003286 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003287
William Lallemand7f80eb22017-05-26 18:19:55 +02003288 /* pass through every cli socket, and check if it's bound to
3289 * the current process and if it exposes listeners sockets.
3290 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3291 * */
3292
Willy Tarreau4975d142021-03-13 11:00:33 +01003293 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003294 struct bind_conf *bind_conf;
3295
Willy Tarreau4975d142021-03-13 11:00:33 +01003296 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003297 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreaue26993c2020-09-03 07:18:55 +02003298 if (!bind_conf->settings.bind_proc || bind_conf->settings.bind_proc & (1UL << proc)) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003299 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3300 break;
3301 }
3302 }
3303 }
3304 }
3305
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003306 /* we might have to unbind some proxies from some processes */
Olivier Houchardfbc74e82017-11-24 16:54:05 +01003307 px = proxies_list;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003308 while (px != NULL) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02003309 if (px->bind_proc && !px->disabled) {
Willy Tarreau337c8352020-09-24 10:51:29 +02003310 if (!(px->bind_proc & (1UL << proc)))
3311 stop_proxy(px);
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003312 }
3313 px = px->next;
3314 }
3315
Emeric Brunc47ba592020-10-07 10:13:10 +02003316 /* we might have to unbind some log forward proxies from some processes */
3317 px = cfg_log_forward;
3318 while (px != NULL) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02003319 if (px->bind_proc && !px->disabled) {
Willy Tarreau337c8352020-09-24 10:51:29 +02003320 if (!(px->bind_proc & (1UL << proc)))
3321 stop_proxy(px);
Emeric Brunc47ba592020-10-07 10:13:10 +02003322 }
3323 px = px->next;
3324 }
3325
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003326 /* we might have to unbind some peers sections from some processes */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02003327 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003328 if (!curpeers->peers_fe)
3329 continue;
3330
3331 if (curpeers->peers_fe->bind_proc & (1UL << proc))
3332 continue;
3333
3334 stop_proxy(curpeers->peers_fe);
3335 /* disable this peer section so that it kills itself */
Willy Tarreau47c8c022015-09-28 16:39:25 +02003336 signal_unregister_handler(curpeers->sighandler);
Olivier Houchard3f795f72019-04-17 22:51:06 +02003337 task_destroy(curpeers->sync_task);
Willy Tarreau47c8c022015-09-28 16:39:25 +02003338 curpeers->sync_task = NULL;
Olivier Houchard3f795f72019-04-17 22:51:06 +02003339 task_destroy(curpeers->peers_fe->task);
Willy Tarreau47c8c022015-09-28 16:39:25 +02003340 curpeers->peers_fe->task = NULL;
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003341 curpeers->peers_fe = NULL;
3342 }
3343
William Lallemand2e8fad92018-11-13 16:18:23 +01003344 /*
3345 * This is only done in daemon mode because we might want the
3346 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3347 * we should now close the 3 first FDs to ensure that we can
3348 * detach from the TTY. We MUST NOT do it in other cases since
3349 * it would have already be done, and 0-2 would have been
3350 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003352 if ((global.mode & MODE_DAEMON) &&
3353 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003354 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003355 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003356 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3358 }
3359 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003360 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3361 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003362 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 }
3364
William Dauchye039f262019-11-17 15:47:15 +01003365 /* try our best to re-enable core dumps depending on system capabilities.
3366 * What is addressed here :
3367 * - remove file size limits
3368 * - remove core size limits
3369 * - mark the process dumpable again if it lost it due to user/group
3370 */
3371 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3372 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3373
3374#if defined(RLIMIT_FSIZE)
3375 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3376 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3377 ha_alert("[%s.main()] Failed to set the raise the maximum "
3378 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003379 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003380 }
3381 else
3382 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003383 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003384 }
3385#endif
3386
3387#if defined(RLIMIT_CORE)
3388 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3389 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3390 ha_alert("[%s.main()] Failed to set the raise the core "
3391 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003392 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003393 }
3394 else
3395 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003396 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003397 }
3398#endif
3399
3400#if defined(USE_PRCTL)
3401 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3402 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3403 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com078062b2021-08-21 09:13:10 +01003404#elif defined(USE_PROCCTL)
3405 int traceable = PROC_TRACE_CTL_ENABLE;
3406 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3407 ha_warning("[%s.main()] Failed to set the traceable flag, "
3408 "no core will be dumped.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003409#endif
3410 }
3411
Christopher Faulete3a5e352017-10-24 13:53:54 +02003412 global.mode &= ~MODE_STARTING;
Willy Tarreau4f60f162007-04-08 16:39:58 +02003413 /*
3414 * That's it : the central polling loop. Run until we stop.
3415 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02003416#ifdef USE_THREAD
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003417 {
William Lallemand1aab50b2018-06-07 09:46:01 +02003418 sigset_t blocked_sig, old_sig;
Willy Tarreauc40efc12019-05-03 09:22:44 +02003419 int i;
3420
William Lallemand1aab50b2018-06-07 09:46:01 +02003421 /* ensure the signals will be blocked in every thread */
3422 sigfillset(&blocked_sig);
3423 sigdelset(&blocked_sig, SIGPROF);
3424 sigdelset(&blocked_sig, SIGBUS);
3425 sigdelset(&blocked_sig, SIGFPE);
3426 sigdelset(&blocked_sig, SIGILL);
3427 sigdelset(&blocked_sig, SIGSEGV);
3428 pthread_sigmask(SIG_SETMASK, &blocked_sig, &old_sig);
3429
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003430 /* Create nbthread-1 thread. The first thread is the current process */
David Carliera92c5ce2019-09-13 05:03:12 +01003431 ha_thread_info[0].pthread = pthread_self();
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003432 for (i = 1; i < global.nbthread; i++)
David Carliera92c5ce2019-09-13 05:03:12 +01003433 pthread_create(&ha_thread_info[i].pthread, NULL, &run_thread_poll_loop, (void *)(long)i);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003434
Christopher Faulet62519022017-10-16 15:49:32 +02003435#ifdef USE_CPU_AFFINITY
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003436 /* Now the CPU affinity for all threads */
Amaury Denoyelleaf02c572021-04-15 16:29:58 +02003437
3438 /* If on multiprocess, use proc_t1 except for the first process.
3439 */
3440 if ((relative_pid - 1) > 0)
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003441 cpu_map.thread[0] = cpu_map.proc_t1[relative_pid-1];
Willy Tarreau7764a572019-07-16 15:10:34 +02003442
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003443 for (i = 0; i < global.nbthread; i++) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003444 if (ha_cpuset_count(&cpu_map.proc[relative_pid-1]))
3445 ha_cpuset_and(&cpu_map.thread[i], &cpu_map.proc[relative_pid-1]);
Christopher Faulet62519022017-10-16 15:49:32 +02003446
Willy Tarreau421f02e2018-01-20 18:19:22 +01003447 if (i < MAX_THREADS && /* only the first 32/64 threads may be pinned */
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003448 ha_cpuset_count(&cpu_map.thread[i])) {/* only do this if the thread has a THREAD map */
David Carlier5e4c8e22019-09-13 05:12:58 +01003449#if defined(__APPLE__)
3450 int j;
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003451 unsigned long set = cpu_map.thread[i].cpuset;
David Carlier5e4c8e22019-09-13 05:12:58 +01003452
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003453 while ((j = ffsl(set)) > 0) {
David Carlier5e4c8e22019-09-13 05:12:58 +01003454 thread_affinity_policy_data_t cpu_set = { j - 1 };
3455 thread_port_t mthread = pthread_mach_thread_np(ha_thread_info[i].pthread);
3456 thread_policy_set(mthread, THREAD_AFFINITY_POLICY, (thread_policy_t)&cpu_set, 1);
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003457 set &= ~(1UL << (j - 1));
David Carlier5e4c8e22019-09-13 05:12:58 +01003458 }
3459#else
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003460 struct hap_cpuset *set = &cpu_map.thread[i];
David Carliera92c5ce2019-09-13 05:03:12 +01003461 pthread_setaffinity_np(ha_thread_info[i].pthread,
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003462 sizeof(set->cpuset), &set->cpuset);
David Carlier5e4c8e22019-09-13 05:12:58 +01003463#endif
Olivier Houchard829aa242017-12-01 18:19:43 +01003464 }
Christopher Faulet1d17c102017-08-29 15:38:48 +02003465 }
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003466#endif /* !USE_CPU_AFFINITY */
3467
William Lallemand1aab50b2018-06-07 09:46:01 +02003468 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003469 haproxy_unblock_signals();
William Lallemand1aab50b2018-06-07 09:46:01 +02003470
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003471 /* Finally, start the poll loop for the first thread */
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02003472 run_thread_poll_loop(0);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003473
3474 /* Wait the end of other threads */
3475 for (i = 1; i < global.nbthread; i++)
David Carliera92c5ce2019-09-13 05:03:12 +01003476 pthread_join(ha_thread_info[i].pthread, NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003477
Christopher Fauletb79a94c2017-05-30 15:34:30 +02003478#if defined(DEBUG_THREAD) || defined(DEBUG_FULL)
3479 show_lock_stats();
3480#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003481 }
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003482#else /* ! USE_THREAD */
William Lallemandd3801c12018-09-11 10:06:23 +02003483 haproxy_unblock_signals();
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02003484 run_thread_poll_loop(0);
Christopher Faulet62519022017-10-16 15:49:32 +02003485#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003486
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003487 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003488}
3489
Willy Tarreaubaaee002006-06-26 02:48:02 +02003490/*
3491 * Local variables:
3492 * c-indent-level: 8
3493 * c-basic-offset: 8
3494 * End:
3495 */