blob: e3ccea77e7fea1be95cce7796cfdf019119a1626 [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 Tarreaud10385a2021-10-06 22:22:40 +020053
Willy Tarreau5e03dfa2021-10-06 22:53:51 +020054#ifdef USE_THREAD
55#include <pthread.h>
56#endif
57
Willy Tarreaufc6c0322012-11-16 16:12:27 +010058#ifdef USE_CPU_AFFINITY
Willy Tarreaufc6c0322012-11-16 16:12:27 +010059#include <sched.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000060#if defined(__FreeBSD__) || defined(__DragonFly__)
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020061#include <sys/param.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000062#ifdef __FreeBSD__
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020063#include <sys/cpuset.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000064#endif
David Carlier5e4c8e22019-09-13 05:12:58 +010065#endif
Willy Tarreaufc6c0322012-11-16 16:12:27 +010066#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
Willy Tarreau636848a2019-04-15 19:38:50 +020068#if defined(USE_PRCTL)
69#include <sys/prctl.h>
70#endif
71
devnexen@gmail.com21185972021-08-21 09:13:10 +010072#if defined(USE_PROCCTL)
73#include <sys/procctl.h>
74#endif
75
Willy Tarreaubaaee002006-06-26 02:48:02 +020076#ifdef DEBUG_FULL
77#include <assert.h>
78#endif
Tim Duesterhusd6942c82017-11-20 15:58:35 +010079#if defined(USE_SYSTEMD)
80#include <systemd/sd-daemon.h>
81#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020082
Willy Tarreau6c3a6812020-03-06 18:57:15 +010083#include <import/sha1.h>
84
Willy Tarreaub2551052020-06-09 09:07:15 +020085#include <haproxy/acl.h>
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +010086#include <haproxy/action.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020087#include <haproxy/activity.h>
88#include <haproxy/api.h>
89#include <haproxy/arg.h>
90#include <haproxy/auth.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020091#include <haproxy/base64.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020092#include <haproxy/capture-t.h>
Willy Tarreau66243b42021-07-16 15:39:28 +020093#include <haproxy/cfgcond.h>
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +020094#include <haproxy/cfgdiag.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020095#include <haproxy/cfgparse.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020096#include <haproxy/chunk.h>
Willy Tarreau83487a82020-06-04 20:19:54 +020097#include <haproxy/cli.h>
Willy Tarreau55542642021-10-08 09:33:24 +020098#include <haproxy/clock.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020099#include <haproxy/connection.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200100#ifdef USE_CPU_AFFINITY
Amaury Denoyelle982fb532021-04-21 18:39:58 +0200101#include <haproxy/cpuset.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200102#endif
Willy Tarreaueb92deb2020-06-04 10:53:16 +0200103#include <haproxy/dns.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +0200104#include <haproxy/dynbuf.h>
Willy Tarreau8d366972020-05-27 16:10:29 +0200105#include <haproxy/errors.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200106#include <haproxy/fd.h>
Willy Tarreauc7babd82020-06-04 21:29:29 +0200107#include <haproxy/filters.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200108#include <haproxy/global.h>
Willy Tarreau86416052020-06-04 09:20:54 +0200109#include <haproxy/hlua.h>
Willy Tarreauc761f842020-06-04 11:40:28 +0200110#include <haproxy/http_rules.h>
Willy Tarreau853b2972020-05-27 18:01:47 +0200111#include <haproxy/list.h>
Willy Tarreau213e9902020-06-04 14:58:24 +0200112#include <haproxy/listener.h>
Willy Tarreauaeed4a82020-06-04 22:01:04 +0200113#include <haproxy/log.h>
Willy Tarreaub5abe5b2020-06-04 14:07:37 +0200114#include <haproxy/mworker.h>
Willy Tarreau7a00efb2020-06-02 17:02:59 +0200115#include <haproxy/namespace.h>
Willy Tarreau6131d6a2020-06-02 16:48:09 +0200116#include <haproxy/net_helper.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +0200117#include <haproxy/openssl-compat.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200118#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200119#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200120#include <haproxy/pool.h>
121#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200122#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200123#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200124#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200125#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200126#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200127#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200128#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200129#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200130#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200131#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200132#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200133#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200134#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200135#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200136#include <haproxy/time.h>
137#include <haproxy/tools.h>
138#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200139#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200140#include <haproxy/version.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200141
Willy Tarreaubaaee002006-06-26 02:48:02 +0200142
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100143/* array of init calls for older platforms */
144DECLARE_INIT_STAGES;
145
Willy Tarreauf4596402021-04-10 16:53:05 +0200146/* create a read_mostly section to hold variables which are accessed a lot
147 * but which almost never change. The purpose is to isolate them in their
148 * own cache lines where they don't risk to be perturbated by write accesses
149 * to neighbor variables. We need to create an empty aligned variable for
150 * this. The fact that the variable is of size zero means that it will be
151 * eliminated at link time if no other variable uses it, but alignment will
152 * be respected.
153 */
154empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
155
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200156#ifdef BUILD_FEATURES
157const char *build_features = BUILD_FEATURES;
158#else
159const char *build_features = "";
160#endif
161
Willy Tarreau477ecd82010-01-03 21:12:30 +0100162/* list of config files */
163static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164int pid; /* current process id */
165
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100166volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100167volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100168
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169/* global options */
170struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100171 .hard_stop_after = TICK_ETERNITY,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100172 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100173 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200174 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200175 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
William Lallemand9d5f5482012-11-07 16:12:57 +0100176 .maxzlibmem = 0,
William Lallemandd85f9172012-11-09 17:05:39 +0100177 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100178 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200179 .unix_bind = {
180 .ux = {
181 .uid = -1,
182 .gid = -1,
183 .mode = 0,
184 }
185 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200186 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100187 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100188 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100189 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100190 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200191 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200192 .pool_low_ratio = 20,
193 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200194 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200195#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100196 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200197#endif
William Lallemandf3747832012-11-09 12:33:10 +0100198 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100199#ifdef DEFAULT_IDLE_TIMER
200 .idle_timer = DEFAULT_IDLE_TIMER,
201#else
202 .idle_timer = 1000, /* 1 second */
203#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200204 },
Emeric Brun76d88952012-10-05 15:47:31 +0200205#ifdef USE_OPENSSL
206#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200207 .maxsslconn = DEFAULT_MAXSSLCONN,
208#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200209#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210 /* others NULL OK */
211};
212
213/*********************************************************************/
214
215int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100216int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200217int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100218int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100219int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100220int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500222/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 * or kill. We will send them a signal every 10 ms until we can bind to all
224 * our ports. With 200 retries, that's about 2 seconds.
225 */
226#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227static int *oldpids = NULL;
228static int oldpids_sig; /* use USR1 or TERM */
229
Olivier Houchardf73629d2017-04-05 22:33:04 +0200230/* Path to the unix socket we use to retrieve listener sockets from the old process */
231static const char *old_unixsocket;
232
William Lallemand85b0bd92017-06-01 17:38:53 +0200233static char *cur_unixsocket = NULL;
234
William Lallemandcb11fd22017-06-01 17:38:52 +0200235int atexit_flag = 0;
236
Willy Tarreaubb545b42010-08-25 12:58:59 +0200237int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238const int zero = 0;
239const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200240const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100242char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200243char *localpeer = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
William Lallemand00417412020-06-05 14:08:41 +0200245static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200246
William Lallemandbc193052018-09-11 10:06:26 +0200247struct list proc_list = LIST_HEAD_INIT(proc_list);
248
249int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100250unsigned int rlim_fd_cur_at_boot = 0;
251unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200252
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100253/* per-boot randomness */
254unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
255
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200256/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200257static void *run_thread_poll_loop(void *data);
258
Willy Tarreauff055502014-04-28 22:27:06 +0200259/* bitfield of a few warnings to emit just once (WARN_*) */
260unsigned int warned = 0;
261
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200262/* set if experimental features have been used for the current process */
263static unsigned int tainted = 0;
264
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200265unsigned int experimental_directives_allowed = 0;
266
267int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
268 char **errmsg)
269{
270 if (kw->flags & KWF_EXPERIMENTAL) {
271 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200272 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 +0200273 file, linenum, kw->kw);
274 return 1;
275 }
276 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
277 }
278
279 return 0;
280}
281
William Lallemande7361152018-10-26 14:47:36 +0200282/* master CLI configuration (-S flag) */
283struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100284
285/* These are strings to be reported in the output of "haproxy -vv". They may
286 * either be constants (in which case must_free must be zero) or dynamically
287 * allocated strings to pass to free() on exit, and in this case must_free
288 * must be non-zero.
289 */
290struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
291struct build_opts_str {
292 struct list list;
293 const char *str;
294 int must_free;
295};
296
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297/*********************************************************************/
298/* general purpose functions ***************************************/
299/*********************************************************************/
300
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100301/* used to register some build option strings at boot. Set must_free to
302 * non-zero if the string must be freed upon exit.
303 */
304void hap_register_build_opts(const char *str, int must_free)
305{
306 struct build_opts_str *b;
307
308 b = calloc(1, sizeof(*b));
309 if (!b) {
310 fprintf(stderr, "out of memory\n");
311 exit(1);
312 }
313 b->str = str;
314 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200315 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100316}
317
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200318#define VERSION_MAX_ELTS 7
319
320/* This function splits an haproxy version string into an array of integers.
321 * The syntax of the supported version string is the following:
322 *
323 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
324 *
325 * This validates for example:
326 * 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
327 * 2.4-dev18-f6818d-20
328 *
329 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
330 * one fixed place in the array. The tags take a numeric value called <e> which
331 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
332 * considered as zero (henxe 1.5 and 1.5.0 are the same).
333 *
334 * The resulting values are:
335 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
336 * 1.2.1 1, 2, 1, 0, 3, 0, 0
337 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
338 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
339 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
340 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
341 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
342 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
343 *
344 * The function returns non-zero if the conversion succeeded, or zero if it
345 * failed.
346 */
347int split_version(const char *version, unsigned int *value)
348{
349 const char *p, *s;
350 char *error;
351 int nelts;
352
353 /* Initialize array with zeroes */
354 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
355 value[nelts] = 0;
356 value[4] = 3;
357
358 p = version;
359
360 /* If the version number is empty, return false */
361 if (*p == '\0')
362 return 0;
363
364 /* Convert first number <a> */
365 value[0] = strtol(p, &error, 10);
366 p = error + 1;
367 if (*error == '\0')
368 return 1;
369 if (*error == '-')
370 goto split_version_tag;
371 if (*error != '.')
372 return 0;
373
374 /* Convert first number <b> */
375 value[1] = strtol(p, &error, 10);
376 p = error + 1;
377 if (*error == '\0')
378 return 1;
379 if (*error == '-')
380 goto split_version_tag;
381 if (*error != '.')
382 return 0;
383
384 /* Convert first number <c> */
385 value[2] = strtol(p, &error, 10);
386 p = error + 1;
387 if (*error == '\0')
388 return 1;
389 if (*error == '-')
390 goto split_version_tag;
391 if (*error != '.')
392 return 0;
393
394 /* Convert first number <d> */
395 value[3] = strtol(p, &error, 10);
396 p = error + 1;
397 if (*error == '\0')
398 return 1;
399 if (*error != '-')
400 return 0;
401
402 split_version_tag:
403 /* Check for commit number */
404 if (*p >= '0' && *p <= '9')
405 goto split_version_commit;
406
407 /* Read tag */
408 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
409 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
410 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
411 else
412 goto split_version_commit;
413
414 /* Convert tag number */
415 value[5] = strtol(p, &error, 10);
416 p = error + 1;
417 if (*error == '\0')
418 return 1;
419 if (*error != '-')
420 return 0;
421
422 split_version_commit:
423 /* Search the last "-" */
424 s = strrchr(p, '-');
425 if (s) {
426 s++;
427 if (*s == '\0')
428 return 0;
429 value[6] = strtol(s, &error, 10);
430 if (*error != '\0')
431 value[6] = 0;
432 return 1;
433 }
434
435 /* convert the version */
436 value[6] = strtol(p, &error, 10);
437 if (*error != '\0')
438 value[6] = 0;
439
440 return 1;
441}
442
443/* This function compares the current haproxy version with an arbitrary version
444 * string. It returns:
445 * -1 : the version in argument is older than the current haproxy version
446 * 0 : the version in argument is the same as the current haproxy version
447 * 1 : the version in argument is newer than the current haproxy version
448 *
449 * Or some errors:
450 * -2 : the current haproxy version is not parsable
451 * -3 : the version in argument is not parsable
452 */
453int compare_current_version(const char *version)
454{
455 unsigned int loc[VERSION_MAX_ELTS];
456 unsigned int mod[VERSION_MAX_ELTS];
457 int i;
458
459 /* split versions */
460 if (!split_version(haproxy_version, loc))
461 return -2;
462 if (!split_version(version, mod))
463 return -3;
464
465 /* compare versions */
466 for (i = 0; i < VERSION_MAX_ELTS; i++) {
467 if (mod[i] < loc[i])
468 return -1;
469 else if (mod[i] > loc[i])
470 return 1;
471 }
472 return 0;
473}
474
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100475static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200477 struct utsname utsname;
478
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200479 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100480 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100481
482 if (strlen(PRODUCT_URL_BUGS) > 0) {
483 char base_version[20];
484 int dots = 0;
485 char *del;
486
487 /* only retrieve the base version without distro-specific extensions */
488 for (del = haproxy_version; *del; del++) {
489 if (*del == '.')
490 dots++;
491 else if (*del < '0' || *del > '9')
492 break;
493 }
494
495 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
496 if (dots < 2)
497 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
498 else
499 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
500 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200501
502 if (uname(&utsname) == 0) {
503 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
504 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200505}
506
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100507static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100508{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100509 struct build_opts_str *item;
510
Willy Tarreau7b066db2007-12-02 11:28:59 +0100511 printf("Build options :"
512#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100513 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100514#endif
515#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100516 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100517#endif
518#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100519 "\n CC = " BUILD_CC
520#endif
521#ifdef BUILD_CFLAGS
522 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100523#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100524#ifdef BUILD_OPTIONS
525 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100526#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100527#ifdef BUILD_DEBUG
528 "\n DEBUG = " BUILD_DEBUG
529#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100530#ifdef BUILD_FEATURES
531 "\n\nFeature list : " BUILD_FEATURES
532#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200533 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100534 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200535 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100536 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200537
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100538 list_for_each_entry(item, &build_opts_list, list) {
539 puts(item->str);
540 }
541
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100542 putchar('\n');
543
Willy Tarreaube5b6852009-10-03 18:57:08 +0200544 list_pollers(stdout);
545 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200546 list_mux_proto(stdout);
547 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100548 list_services(stdout);
549 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100550 list_filters(stdout);
551 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100552}
553
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554/*
555 * This function prints the command line usage and exits
556 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100557static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200558{
559 display_version();
560 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200561 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200562 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200563 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100564 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200565 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreau6e064432012-05-08 15:40:42 +0200566 " -dM[<byte>] poisons memory with <byte> (defaults to 0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200568 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200569 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100570#if defined(USE_SYSTEMD)
571 " -Ws master-worker mode with systemd notify support.\n"
572#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200573 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200574 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200575 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100576 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 " -m limits the usable amount of memory (in MB)\n"
578 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200579 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200581#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582 " -de disables epoll() usage even when available\n"
583#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200584#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200585 " -dk disables kqueue() usage even when available\n"
586#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200587#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000588 " -dv disables event ports usage even when available\n"
589#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200590#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200591 " -dp disables poll() usage even when available\n"
592#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200593#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100594 " -dS disables splice usage (broken on old kernels)\n"
595#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200596#if defined(USE_GETADDRINFO)
597 " -dG disables getaddrinfo() usage\n"
598#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000599#if defined(SO_REUSEPORT)
600 " -dR disables SO_REUSEPORT usage\n"
601#endif
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100602 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100603 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200604 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200605 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200606 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200607 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200608 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100610 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 exit(1);
612}
613
614
615
616/*********************************************************************/
617/* more specific functions ***************************************/
618/*********************************************************************/
619
William Lallemand73b85e72017-06-01 17:38:51 +0200620/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
621 * pids the signal was correctly delivered to.
622 */
William Lallemande25473c2019-04-01 11:29:56 +0200623int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200624{
625 int p;
626 int ret = 0;
627 for (p = 0; p < nb_oldpids; p++)
628 if (kill(oldpids[p], sig) == 0)
629 ret++;
630 return ret;
631}
632
William Lallemand75ea0a02017-11-15 19:02:58 +0100633/*
William Lallemand73b85e72017-06-01 17:38:51 +0200634 * remove a pid forom the olpid array and decrease nb_oldpids
635 * return 1 pid was found otherwise return 0
636 */
637
638int delete_oldpid(int pid)
639{
640 int i;
641
642 for (i = 0; i < nb_oldpids; i++) {
643 if (oldpids[i] == pid) {
644 oldpids[i] = oldpids[nb_oldpids - 1];
645 oldpids[nb_oldpids - 1] = 0;
646 nb_oldpids--;
647 return 1;
648 }
649 }
650 return 0;
651}
652
William Lallemand85b0bd92017-06-01 17:38:53 +0200653
654static void get_cur_unixsocket()
655{
656 /* if -x was used, try to update the stat socket if not available anymore */
Willy Tarreau4975d142021-03-13 11:00:33 +0100657 if (global.cli_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200658 struct bind_conf *bind_conf;
659
660 /* pass through all stats socket */
Willy Tarreau4975d142021-03-13 11:00:33 +0100661 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200662 struct listener *l;
663
664 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
665
Willy Tarreau37159062020-08-27 07:48:42 +0200666 if (l->rx.addr.ss_family == AF_UNIX &&
William Lallemand85b0bd92017-06-01 17:38:53 +0200667 (bind_conf->level & ACCESS_FD_LISTENERS)) {
668 const struct sockaddr_un *un;
669
Willy Tarreau37159062020-08-27 07:48:42 +0200670 un = (struct sockaddr_un *)&l->rx.addr;
William Lallemand85b0bd92017-06-01 17:38:53 +0200671 /* priority to old_unixsocket */
672 if (!cur_unixsocket) {
673 cur_unixsocket = strdup(un->sun_path);
674 } else {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100675 if (old_unixsocket && strcmp(un->sun_path, old_unixsocket) == 0) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200676 free(cur_unixsocket);
677 cur_unixsocket = strdup(old_unixsocket);
678 return;
679 }
680 }
681 }
682 }
683 }
684 }
685 if (!cur_unixsocket && old_unixsocket)
686 cur_unixsocket = strdup(old_unixsocket);
687}
688
William Lallemand73b85e72017-06-01 17:38:51 +0200689/*
690 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800691 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200692 */
William Lallemanda57b7e32018-12-14 21:11:31 +0100693void mworker_reload()
William Lallemand73b85e72017-06-01 17:38:51 +0200694{
William Lallemand00417412020-06-05 14:08:41 +0200695 char **next_argv = NULL;
696 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200697 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200698 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200699 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100700 struct rlimit limit;
William Lallemand7c756a82018-11-26 11:53:40 +0100701 struct per_thread_deinit_fct *ptdf;
William Lallemand73b85e72017-06-01 17:38:51 +0200702
703 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100704#if defined(USE_SYSTEMD)
705 if (global.tune.options & GTUNE_USE_SYSTEMD)
706 sd_notify(0, "RELOADING=1");
707#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200708 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
709
William Lallemandbc193052018-09-11 10:06:26 +0200710 mworker_proc_list_to_env(); /* put the children description in the env */
711
William Lallemand7c756a82018-11-26 11:53:40 +0100712 /* during the reload we must ensure that every FDs that can't be
713 * reuse (ie those that are not referenced in the proc_list)
714 * are closed or they will leak. */
715
716 /* close the listeners FD */
717 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200718
719 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
720 /* close the poller FD and the thread waker pipe FD */
721 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
722 ptdf->fct();
723 if (fdtab)
724 deinit_pollers();
725 }
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500726#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200727 /* close random device FDs */
728 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100729#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100730
Willy Tarreau8dca1952019-03-01 10:21:55 +0100731 /* restore the initial FD limits */
732 limit.rlim_cur = rlim_fd_cur_at_boot;
733 limit.rlim_max = rlim_fd_max_at_boot;
734 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
735 getrlimit(RLIMIT_NOFILE, &limit);
736 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
737 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
738 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
739 }
740
William Lallemand73b85e72017-06-01 17:38:51 +0200741 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200742 while (old_argv[old_argc])
743 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200744
William Lallemand85b0bd92017-06-01 17:38:53 +0200745 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200746 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200747 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200748 if (next_argv == NULL)
749 goto alloc_error;
750
William Lallemand00417412020-06-05 14:08:41 +0200751 /* copy the program name */
752 next_argv[next_argc++] = old_argv[0];
753
754 /* insert the new options just after argv[0] in case we have a -- */
755
William Lallemand73b85e72017-06-01 17:38:51 +0200756 /* add -sf <PID>* to argv */
William Lallemand3f128872019-04-01 11:29:59 +0200757 if (mworker_child_nb() > 0) {
758 struct mworker_proc *child;
759
William Lallemand73b85e72017-06-01 17:38:51 +0200760 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200761
762 list_for_each_entry(child, &proc_list, list) {
William Lallemand677e2f22019-11-19 17:04:18 +0100763 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1 )
William Lallemand3f128872019-04-01 11:29:59 +0200764 continue;
William Lallemand00417412020-06-05 14:08:41 +0200765 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
William Lallemand73b85e72017-06-01 17:38:51 +0200766 goto alloc_error;
767 msg = NULL;
768 }
769 }
William Lallemand2bf6d622017-06-20 11:20:23 +0200770 /* add the -x option with the stat socket */
William Lallemand85b0bd92017-06-01 17:38:53 +0200771 if (cur_unixsocket) {
William Lallemand2bf6d622017-06-20 11:20:23 +0200772 next_argv[next_argc++] = "-x";
773 next_argv[next_argc++] = (char *)cur_unixsocket;
William Lallemand85b0bd92017-06-01 17:38:53 +0200774 }
775
William Lallemand00417412020-06-05 14:08:41 +0200776 /* copy the previous options */
777 for (i = 1; i < old_argc; i++)
778 next_argv[next_argc++] = old_argv[i];
779
Christopher Faulet767a84b2017-11-24 16:50:31 +0100780 ha_warning("Reexecuting Master process\n");
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200781 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100782 execvp(next_argv[0], next_argv);
William Lallemand73b85e72017-06-01 17:38:51 +0200783
Christopher Faulet767a84b2017-11-24 16:50:31 +0100784 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100785 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100786 return;
787
William Lallemand73b85e72017-06-01 17:38:51 +0200788alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100789 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800790 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200791 return;
792}
793
William Lallemandb3f2be32018-09-11 10:06:18 +0200794static void mworker_loop()
795{
796
797#if defined(USE_SYSTEMD)
798 if (global.tune.options & GTUNE_USE_SYSTEMD)
799 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
800#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200801 /* Busy polling makes no sense in the master :-) */
802 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200803
William Lallemandbc193052018-09-11 10:06:26 +0200804 master = 1;
805
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100806 signal_unregister(SIGTTIN);
807 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100808 signal_unregister(SIGUSR1);
809 signal_unregister(SIGHUP);
810 signal_unregister(SIGQUIT);
811
William Lallemandb3f2be32018-09-11 10:06:18 +0200812 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
813 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100814 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
815 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200816 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
817 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
818 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
819 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
820
821 mworker_unblock_signals();
822 mworker_cleanlisteners();
William Lallemand27f3fa52018-12-06 14:05:20 +0100823 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200824
William Lallemandbc193052018-09-11 10:06:26 +0200825 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
826 some SIGCHLD were lost */
827
William Lallemandb3f2be32018-09-11 10:06:18 +0200828 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200829
William Lallemand2672eb92018-12-14 15:52:39 +0100830#ifdef USE_THREAD
831 tid_bit = 1;
832 all_threads_mask = 1;
833#endif
834
William Lallemandb3f2be32018-09-11 10:06:18 +0200835 jobs++; /* this is the "master" job, we want to take care of the
836 signals even if there is no listener so the poll loop don't
837 leave */
838
839 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200840 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200841}
William Lallemandcb11fd22017-06-01 17:38:52 +0200842
843/*
844 * Reexec the process in failure mode, instead of exiting
845 */
846void reexec_on_failure()
847{
848 if (!atexit_flag)
849 return;
850
851 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
852
Christopher Faulet767a84b2017-11-24 16:50:31 +0100853 ha_warning("Reexecuting Master process in waitpid mode\n");
William Lallemandcb11fd22017-06-01 17:38:52 +0200854 mworker_reload();
William Lallemandcb11fd22017-06-01 17:38:52 +0200855}
William Lallemand73b85e72017-06-01 17:38:51 +0200856
857
858/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200859 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
860 * a signal zero to all subscribers. This means that it's as easy as
861 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200862 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100863static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864{
865 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200866 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100867 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200868}
869
870/*
871 * upon SIGTTOU, we pause everything
872 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100873static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200874{
Willy Tarreau775e0012020-09-24 16:36:26 +0200875 if (protocol_pause_all() & ERR_FATAL) {
876 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200877 ha_warning("%s", msg);
878 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200879 soft_stop();
880 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100881 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882}
883
884/*
885 * upon SIGTTIN, let's have a soft stop.
886 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100887static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888{
Willy Tarreau775e0012020-09-24 16:36:26 +0200889 if (protocol_resume_all() & ERR_FATAL) {
890 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 +0200891 ha_warning("%s", msg);
892 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200894}
895
896/*
897 * this function dumps every server's state when the process receives SIGHUP.
898 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100899static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100901 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902
Christopher Faulet767a84b2017-11-24 16:50:31 +0100903 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 while (p) {
905 struct server *s = p->srv;
906
907 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
908 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100909 chunk_printf(&trash,
910 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
911 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200912 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200913 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200914 ha_warning("%s\n", trash.area);
915 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916 s = s->next;
917 }
918
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200919 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
920 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100921 chunk_printf(&trash,
922 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
923 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200924 p->feconn, p->beconn, p->totpend, p->queue.length, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200925 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100926 chunk_printf(&trash,
927 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
928 p->id,
929 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200930 p->feconn, p->beconn, p->totpend, p->queue.length, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100932 chunk_printf(&trash,
933 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
934 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
935 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200936 p->feconn, p->beconn, p->totpend, p->queue.length, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200937 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200938 ha_warning("%s\n", trash.area);
939 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940
941 p = p->next;
942 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943}
944
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100945static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200947 /* dump memory usage then free everything possible */
948 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100949 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950}
951
William Lallemande1340412017-12-28 16:09:36 +0100952/*
953 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
954 * If <fd> < 0, it opens /dev/null and use it to dup
955 *
956 * In the case of chrooting, you have to open /dev/null before the chroot, and
957 * pass the <fd> to this function
958 */
959static void stdio_quiet(int fd)
960{
961 if (fd < 0)
962 fd = open("/dev/null", O_RDWR, 0);
963
964 if (fd > -1) {
965 fclose(stdin);
966 fclose(stdout);
967 fclose(stderr);
968
969 dup2(fd, 0);
970 dup2(fd, 1);
971 dup2(fd, 2);
972 if (fd > 2)
973 close(fd);
974 return;
975 }
976
977 ha_alert("Cannot open /dev/null\n");
978 exit(EXIT_FAILURE);
979}
980
981
Joseph Herlant03420902018-11-15 10:41:50 -0800982/* This function checks if cfg_cfgfiles contains directories.
983 * If it finds one, it adds all the files (and only files) it contains
984 * in cfg_cfgfiles in place of the directory (and removes the directory).
985 * It adds the files in lexical order.
986 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200987 * It doesn't add files with name starting with '.'
988 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100989static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200990{
991 struct wordlist *wl, *wlb;
992 char *err = NULL;
993
994 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
995 struct stat file_stat;
996 struct dirent **dir_entries = NULL;
997 int dir_entries_nb;
998 int dir_entries_it;
999
1000 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001001 ha_alert("Cannot open configuration file/directory %s : %s\n",
1002 wl->s,
1003 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001004 exit(1);
1005 }
1006
1007 if (!S_ISDIR(file_stat.st_mode))
1008 continue;
1009
1010 /* from this point wl->s is a directory */
1011
1012 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1013 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001014 ha_alert("Cannot open configuration directory %s : %s\n",
1015 wl->s,
1016 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001017 exit(1);
1018 }
1019
1020 /* for each element in the directory wl->s */
1021 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1022 struct dirent *dir_entry = dir_entries[dir_entries_it];
1023 char *filename = NULL;
1024 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1025
1026 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001027 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001028 */
1029 if (dir_entry->d_name[0] == '.' ||
1030 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1031 goto next_dir_entry;
1032
1033 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001034 ha_alert("Cannot load configuration files %s : out of memory.\n",
1035 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001036 exit(1);
1037 }
1038
1039 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001040 ha_alert("Cannot open configuration file %s : %s\n",
1041 wl->s,
1042 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001043 exit(1);
1044 }
1045
1046 /* don't add anything else than regular file in cfg_cfgfiles
1047 * this way we avoid loops
1048 */
1049 if (!S_ISREG(file_stat.st_mode))
1050 goto next_dir_entry;
1051
1052 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001053 ha_alert("Cannot load configuration files %s : %s\n",
1054 filename,
1055 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001056 exit(1);
1057 }
1058
1059next_dir_entry:
1060 free(filename);
1061 free(dir_entry);
1062 }
1063
1064 free(dir_entries);
1065
1066 /* remove the current directory (wl) from cfg_cfgfiles */
1067 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001068 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001069 free(wl);
1070 }
1071
1072 free(err);
1073}
1074
Willy Tarreaubaaee002006-06-26 02:48:02 +02001075/*
William Lallemand73b85e72017-06-01 17:38:51 +02001076 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001077 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001078 * Return an allocated copy of argv
1079 */
1080
1081static char **copy_argv(int argc, char **argv)
1082{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001083 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001084
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001085 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001086 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001087 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001088 return NULL;
1089 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001090 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001091
William Lallemanddf6c5a82020-06-04 17:40:23 +02001092 /* first copy argv[0] */
1093 *newargv++ = *argv++;
1094 argc--;
1095
1096 while (argc > 0) {
1097 if (**argv != '-') {
1098 /* non options are copied but will fail in the argument parser */
1099 *newargv++ = *argv++;
1100 argc--;
1101
1102 } else {
1103 char *flag;
1104
1105 flag = *argv + 1;
1106
1107 if (flag[0] == '-' && flag[1] == 0) {
1108 /* "--\0" copy every arguments till the end of argv */
1109 *newargv++ = *argv++;
1110 argc--;
1111
1112 while (argc > 0) {
1113 *newargv++ = *argv++;
1114 argc--;
1115 }
1116 } else {
1117 switch (*flag) {
1118 case 's':
1119 /* -sf / -st and their parameters are ignored */
1120 if (flag[1] == 'f' || flag[1] == 't') {
1121 argc--;
1122 argv++;
1123 /* The list can't contain a negative value since the only
1124 way to know the end of this list is by looking for the
1125 next option or the end of the options */
1126 while (argc > 0 && argv[0][0] != '-') {
1127 argc--;
1128 argv++;
1129 }
William Lallemand398da622020-09-02 16:12:23 +02001130 } else {
1131 argc--;
1132 argv++;
1133
William Lallemanddf6c5a82020-06-04 17:40:23 +02001134 }
1135 break;
1136
1137 case 'x':
1138 /* this option and its parameter are ignored */
1139 argc--;
1140 argv++;
1141 if (argc > 0) {
1142 argc--;
1143 argv++;
1144 }
1145 break;
1146
1147 case 'C':
1148 case 'n':
1149 case 'm':
1150 case 'N':
1151 case 'L':
1152 case 'f':
1153 case 'p':
1154 case 'S':
1155 /* these options have only 1 parameter which must be copied and can start with a '-' */
1156 *newargv++ = *argv++;
1157 argc--;
1158 if (argc == 0)
1159 goto error;
1160 *newargv++ = *argv++;
1161 argc--;
1162 break;
1163 default:
1164 /* for other options just copy them without parameters, this is also done
1165 * for options like "--foo", but this will fail in the argument parser.
1166 * */
1167 *newargv++ = *argv++;
1168 argc--;
1169 break;
1170 }
William Lallemand73b85e72017-06-01 17:38:51 +02001171 }
1172 }
William Lallemand73b85e72017-06-01 17:38:51 +02001173 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001174
William Lallemanddf6c5a82020-06-04 17:40:23 +02001175 return retargv;
1176
1177error:
1178 free(retargv);
1179 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001180}
1181
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001182
1183/* Performs basic random seed initialization. The main issue with this is that
1184 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1185 * which means that there will only be 4 billion possible random sequences once
1186 * srandom() is called, regardless of the internal state. Not calling it is
1187 * even worse as we'll always produce the same randoms sequences. What we do
1188 * here is to create an initial sequence from various entropy sources, hash it
1189 * using SHA1 and keep the resulting 160 bits available globally.
1190 *
1191 * We initialize the current process with the first 32 bits before starting the
1192 * polling loop, where all this will be changed to have process specific and
1193 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001194 *
1195 * Before starting threads, it's still possible to call random() as srandom()
1196 * is initialized from this, but after threads and/or processes are started,
1197 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001198 */
1199static void ha_random_boot(char *const *argv)
1200{
1201 unsigned char message[256];
1202 unsigned char *m = message;
1203 struct timeval tv;
1204 blk_SHA_CTX ctx;
1205 unsigned long l;
1206 int fd;
1207 int i;
1208
1209 /* start with current time as pseudo-random seed */
1210 gettimeofday(&tv, NULL);
1211 write_u32(m, tv.tv_sec); m += 4;
1212 write_u32(m, tv.tv_usec); m += 4;
1213
1214 /* PID and PPID add some OS-based randomness */
1215 write_u16(m, getpid()); m += 2;
1216 write_u16(m, getppid()); m += 2;
1217
1218 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1219 fd = open("/dev/urandom", O_RDONLY);
1220 if (fd >= 0) {
1221 i = read(fd, m, 20);
1222 if (i > 0)
1223 m += i;
1224 close(fd);
1225 }
1226
1227 /* take up to 160 bits bytes from openssl (non-blocking) */
1228#ifdef USE_OPENSSL
1229 if (RAND_bytes(m, 20) == 1)
1230 m += 20;
1231#endif
1232
1233 /* take 160 bits from existing random in case it was already initialized */
1234 for (i = 0; i < 5; i++) {
1235 write_u32(m, random());
1236 m += 4;
1237 }
1238
1239 /* stack address (benefit form operating system's ASLR) */
1240 l = (unsigned long)&m;
1241 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1242
1243 /* argv address (benefit form operating system's ASLR) */
1244 l = (unsigned long)&argv;
1245 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1246
1247 /* use tv_usec again after all the operations above */
1248 gettimeofday(&tv, NULL);
1249 write_u32(m, tv.tv_usec); m += 4;
1250
1251 /*
1252 * At this point, ~84-92 bytes have been used
1253 */
1254
1255 /* finish with the hostname */
1256 strncpy((char *)m, hostname, message + sizeof(message) - m);
1257 m += strlen(hostname);
1258
1259 /* total message length */
1260 l = m - message;
1261
1262 memset(&ctx, 0, sizeof(ctx));
1263 blk_SHA1_Init(&ctx);
1264 blk_SHA1_Update(&ctx, message, l);
1265 blk_SHA1_Final(boot_seed, &ctx);
1266
1267 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001268 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001269}
1270
Willy Tarreau5a023f02019-03-01 14:19:31 +01001271/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1272 * setting, and returns it. It may return -1 meaning "unlimited" if some
1273 * unlimited proxies have been found and the global.maxconn value is not yet
1274 * set. It may also return a value greater than maxconn if it's not yet set.
1275 * Note that a value of zero means there is no need for pipes. -1 is never
1276 * returned if global.maxconn is valid.
1277 */
1278static int compute_ideal_maxpipes()
1279{
1280 struct proxy *cur;
1281 int nbfe = 0, nbbe = 0;
1282 int unlimited = 0;
1283 int pipes;
1284 int max;
1285
1286 for (cur = proxies_list; cur; cur = cur->next) {
1287 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1288 if (cur->cap & PR_CAP_FE) {
1289 max = cur->maxconn;
1290 nbfe += max;
1291 if (!max) {
1292 unlimited = 1;
1293 break;
1294 }
1295 }
1296 if (cur->cap & PR_CAP_BE) {
1297 max = cur->fullconn ? cur->fullconn : global.maxconn;
1298 nbbe += max;
1299 if (!max) {
1300 unlimited = 1;
1301 break;
1302 }
1303 }
1304 }
1305 }
1306
1307 pipes = MAX(nbfe, nbbe);
1308 if (global.maxconn) {
1309 if (pipes > global.maxconn || unlimited)
1310 pipes = global.maxconn;
1311 } else if (unlimited) {
1312 pipes = -1;
1313 }
1314
1315 return pipes >= 4 ? pipes / 4 : pipes;
1316}
1317
Willy Tarreauac350932019-03-01 15:43:14 +01001318/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1319 * rlimits and computes an ideal maxconn. It's meant to be called only when
1320 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001321 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1322 * default 100) is returned as it is expected that it will even run on tight
1323 * environments, and will maintain compatibility with previous packages that
1324 * used to rely on this value as the default one. The system will emit a
1325 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001326 */
1327static int compute_ideal_maxconn()
1328{
1329 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1330 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1331 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001332 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001333 int maxconn;
1334
1335 /* we have to take into account these elements :
1336 * - number of engine_fds, which inflates the number of FD needed per
1337 * connection by this number.
1338 * - number of pipes per connection on average : for the unlimited
1339 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1340 * fixed value of 2*pipes.
1341 * - two FDs per connection
1342 */
1343
1344 /* subtract listeners and checks */
1345 remain -= global.maxsock;
1346
Willy Tarreau3f200852019-03-14 19:13:17 +01001347 /* one epoll_fd/kqueue_fd per thread */
1348 remain -= global.nbthread;
1349
1350 /* one wake-up pipe (2 fd) per thread */
1351 remain -= 2 * global.nbthread;
1352
Willy Tarreauac350932019-03-01 15:43:14 +01001353 /* Fixed pipes values : we only subtract them if they're not larger
1354 * than the remaining FDs because pipes are optional.
1355 */
1356 if (pipes >= 0 && pipes * 2 < remain)
1357 remain -= pipes * 2;
1358
1359 if (pipes < 0) {
1360 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1361 * = maxconn * (2 + 0.5 + engine_fds)
1362 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1363 */
1364 maxconn = 2 * remain / (5 + 2 * engine_fds);
1365 } else {
1366 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1367 * = maxconn * (2 + engine_fds)
1368 */
1369 maxconn = remain / (2 + engine_fds);
1370 }
1371
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001372 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001373}
1374
Willy Tarreaua409f302020-03-10 17:08:53 +01001375/* computes the estimated maxsock value for the given maxconn based on the
1376 * possibly set global.maxpipes and existing partial global.maxsock. It may
1377 * temporarily change global.maxconn for the time needed to propagate the
1378 * computations, and will reset it.
1379 */
1380static int compute_ideal_maxsock(int maxconn)
1381{
1382 int maxpipes = global.maxpipes;
1383 int maxsock = global.maxsock;
1384
1385
1386 if (!maxpipes) {
1387 int old_maxconn = global.maxconn;
1388
1389 global.maxconn = maxconn;
1390 maxpipes = compute_ideal_maxpipes();
1391 global.maxconn = old_maxconn;
1392 }
1393
1394 maxsock += maxconn * 2; /* each connection needs two sockets */
1395 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1396 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1397 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1398
1399 /* compute fd used by async engines */
1400 if (global.ssl_used_async_engines) {
1401 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1402
1403 maxsock += maxconn * sides * global.ssl_used_async_engines;
1404 }
1405 return maxsock;
1406}
1407
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001408/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001409 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1410 * value is accepted, non-zero otherwise. This is used to determine if an
1411 * automatic limit may be applied or not. When it is not, the caller knows that
1412 * the highest we can do is the rlim_max at boot. In case of error, we return
1413 * that the setting is possible, so that we defer the error processing to the
1414 * final stage in charge of enforcing this.
1415 */
1416static int check_if_maxsock_permitted(int maxsock)
1417{
1418 struct rlimit orig_limit, test_limit;
1419 int ret;
1420
1421 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1422 return 1;
1423
1424 /* don't go further if we can't even set to what we have */
1425 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1426 return 1;
1427
1428 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1429 test_limit.rlim_cur = test_limit.rlim_max;
1430 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1431
1432 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1433 return 1;
1434
1435 return ret == 0;
1436}
1437
Amaury Denoyelle484454d2021-05-05 16:18:45 +02001438void mark_tainted(const enum tainted_flags flag)
1439{
1440 HA_ATOMIC_OR(&tainted, flag);
1441}
1442
1443unsigned int get_tainted()
1444{
1445 int tainted_state;
1446 HA_ATOMIC_STORE(&tainted_state, tainted);
1447 return tainted_state;
1448}
Willy Tarreau304e17e2020-03-10 17:54:54 +01001449
William Lallemand73b85e72017-06-01 17:38:51 +02001450/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02001451 * This function initializes all the necessary variables. It only returns
1452 * if everything is OK. If something fails, it exits.
1453 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001454static void init(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455{
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 int arg_mode = 0; /* MODE_DEBUG, ... */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 char *tmp;
1458 char *cfg_pidfile = NULL;
Willy Tarreau058e9072009-07-20 09:30:05 +02001459 int err_code = 0;
Maxime de Roucy0f503922016-05-13 23:52:55 +02001460 char *err_msg = NULL;
Willy Tarreau477ecd82010-01-03 21:12:30 +01001461 struct wordlist *wl;
Kevinm48936af2010-12-22 16:08:21 +00001462 char *progname;
Willy Tarreau576132e2011-09-10 19:26:56 +02001463 char *change_dir = NULL;
Christopher Fauletd7c91962015-04-30 11:48:27 +02001464 struct proxy *px;
Willy Tarreaue6945732016-12-21 19:57:00 +01001465 struct post_check_fct *pcf;
Willy Tarreauac350932019-03-01 15:43:14 +01001466 int ideal_maxconn;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001467 char *check_condition = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468
Christopher Faulete3a5e352017-10-24 13:53:54 +02001469 global.mode = MODE_STARTING;
William Lallemand00417412020-06-05 14:08:41 +02001470 old_argv = copy_argv(argc, argv);
1471 if (!old_argv) {
William Lallemanddf6c5a82020-06-04 17:40:23 +02001472 ha_alert("failed to copy argv.\n");
1473 exit(1);
1474 }
William Lallemand73b85e72017-06-01 17:38:51 +02001475
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001476 if (!init_trash_buffers(1)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001477 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet748919a2017-07-26 14:59:46 +02001478 exit(1);
1479 }
David du Colombier7af46052012-05-16 14:16:48 +02001480
Emeric Brun2b920a12010-09-23 18:30:22 +02001481 /* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
1482 * the string in case of truncation, and at least FreeBSD appears not to do
1483 * it.
1484 */
1485 memset(hostname, 0, sizeof(hostname));
1486 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001487
1488 if ((localpeer = strdup(hostname)) == NULL) {
1489 ha_alert("Cannot allocate memory for local peer.\n");
1490 exit(EXIT_FAILURE);
1491 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001492 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Emeric Brun2b920a12010-09-23 18:30:22 +02001493
William Lallemand24c928c2020-01-14 17:58:18 +01001494 /* we were in mworker mode, we should restart in mworker mode */
1495 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1496 global.mode |= MODE_MWORKER;
1497
Willy Tarreaubaaee002006-06-26 02:48:02 +02001498 /*
1499 * Initialize the previously static variables.
1500 */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001501
Willy Tarreau173d9952018-01-26 21:48:23 +01001502 totalconn = actconn = listeners = stopping = 0;
Cyril Bonté203ec5a2017-03-23 22:44:13 +01001503 killed = 0;
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001504
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505
1506#ifdef HAPROXY_MEMMAX
Willy Tarreau70060452015-12-14 12:46:07 +01001507 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001508#endif
1509
Benoit GARNIERb413c2a2016-03-27 11:08:03 +02001510 tzset();
Willy Tarreau55542642021-10-08 09:33:24 +02001511 clock_init_process_date();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001512 start_date = now;
1513
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001514 ha_random_boot(argv);
Willy Tarreau84310e22014-02-14 11:59:04 +01001515
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001516 if (init_acl() != 0)
1517 exit(1);
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001518
Amaury Denoyellec593bcd2021-05-19 15:35:29 +02001519#ifdef USE_OPENSSL
1520 /* Initialize the random generator.
1521 * Must be called before chroot for access to /dev/urandom
1522 */
1523 if (!ssl_initialize_random()) {
1524 ha_alert("OpenSSL random data generator initialization failed.\n");
1525 exit(1);
1526 }
1527#endif
1528
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001529 /* Initialise lua. */
1530 hlua_init();
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001531
Christopher Fauletff2613e2016-11-09 11:36:17 +01001532 /* Initialize process vars */
Willy Tarreaub7bfcb32021-08-31 08:13:25 +02001533 vars_init_head(&proc_vars, SCOPE_PROC);
Christopher Fauletff2613e2016-11-09 11:36:17 +01001534
Willy Tarreau43b78992009-01-25 15:42:27 +01001535 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001536#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001537 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001538#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001539#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001540 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001541#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001542#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001543 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001544#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001545#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001546 global.tune.options |= GTUNE_USE_EVPORTS;
1547#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001548#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001549 global.tune.options |= GTUNE_USE_SPLICE;
1550#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001551#if defined(USE_GETADDRINFO)
1552 global.tune.options |= GTUNE_USE_GAI;
1553#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001554#if defined(SO_REUSEPORT)
1555 global.tune.options |= GTUNE_USE_REUSEPORT;
1556#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001557#ifdef USE_THREAD
1558 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1559#endif
William Dauchya5194602020-03-28 19:29:58 +01001560 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561
1562 pid = getpid();
1563 progname = *argv;
1564 while ((tmp = strchr(progname, '/')) != NULL)
1565 progname = tmp + 1;
1566
Kevinm48936af2010-12-22 16:08:21 +00001567 /* the process name is used for the logs only */
Eric Salama7cea6062020-10-02 11:58:19 +02001568 chunk_initlen(&global.log_tag, strdup(progname), strlen(progname), strlen(progname));
1569 if (b_orig(&global.log_tag) == NULL) {
1570 chunk_destroy(&global.log_tag);
1571 ha_alert("Cannot allocate memory for log_tag.\n");
1572 exit(EXIT_FAILURE);
1573 }
Kevinm48936af2010-12-22 16:08:21 +00001574
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575 argc--; argv++;
1576 while (argc > 0) {
1577 char *flag;
1578
1579 if (**argv == '-') {
1580 flag = *argv+1;
1581
1582 /* 1 arg */
1583 if (*flag == 'v') {
1584 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001585 if (flag[1] == 'v') /* -vv */
1586 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 exit(0);
1588 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001589#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001591 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001593#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001595 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001597#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001598 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001599 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001600#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001601#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001602 else if (*flag == 'd' && flag[1] == 'v')
1603 global.tune.options &= ~GTUNE_USE_EVPORTS;
1604#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001605#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001606 else if (*flag == 'd' && flag[1] == 'S')
1607 global.tune.options &= ~GTUNE_USE_SPLICE;
1608#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001609#if defined(USE_GETADDRINFO)
1610 else if (*flag == 'd' && flag[1] == 'G')
1611 global.tune.options &= ~GTUNE_USE_GAI;
1612#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001613#if defined(SO_REUSEPORT)
1614 else if (*flag == 'd' && flag[1] == 'R')
1615 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1616#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001617 else if (*flag == 'd' && flag[1] == 'V')
1618 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001619 else if (*flag == 'V')
1620 arg_mode |= MODE_VERBOSE;
1621 else if (*flag == 'd' && flag[1] == 'b')
1622 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001623 else if (*flag == 'd' && flag[1] == 'D')
1624 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001625 else if (*flag == 'd' && flag[1] == 'W')
1626 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreau6e064432012-05-08 15:40:42 +02001627 else if (*flag == 'd' && flag[1] == 'M')
1628 mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001629 else if (*flag == 'd' && flag[1] == 'r')
1630 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 else if (*flag == 'd')
1632 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001633 else if (*flag == 'c' && flag[1] == 'c') {
1634 arg_mode |= MODE_CHECK_CONDITION;
1635 argv++;
1636 argc--;
1637 check_condition = *argv;
1638 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 else if (*flag == 'c')
1640 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001641 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001642 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001643 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001644 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001645#if defined(USE_SYSTEMD)
1646 global.tune.options |= GTUNE_USE_SYSTEMD;
1647#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001648 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 +01001649 usage(progname);
1650#endif
1651 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001652 else if (*flag == 'W')
1653 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001654 else if (*flag == 'q')
1655 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001656 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001657 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001658 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001659 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001660 }
William Lallemand4fc09692017-06-19 16:37:19 +02001661 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001662 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001663 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001664
Olivier Houchardf73629d2017-04-05 22:33:04 +02001665 argv++;
1666 argc--;
1667 }
William Lallemande7361152018-10-26 14:47:36 +02001668 else if (*flag == 'S') {
1669 struct wordlist *c;
1670
William Lallemanda6b32492020-06-04 23:49:20 +02001671 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001672 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1673 usage(progname);
1674 }
1675 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1676 ha_alert("Cannot allocate memory\n");
1677 exit(EXIT_FAILURE);
1678 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001679 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001680
1681 argv++;
1682 argc--;
1683 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001684 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1685 /* list of pids to finish ('f') or terminate ('t') */
1686
1687 if (flag[1] == 'f')
1688 oldpids_sig = SIGUSR1; /* finish then exit */
1689 else
1690 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001691 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001692 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001693 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1694 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001695 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001696 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001698 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001699 errno = 0;
1700 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1701 if (errno) {
1702 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1703 flag,
1704 *argv, strerror(errno));
1705 exit(1);
1706 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001707 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001708 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001709 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1710 flag, endptr);
1711 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001712 }
Chris Lane236062f2018-02-05 23:15:44 +00001713 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001714 if (oldpids[nb_oldpids] <= 0)
1715 usage(progname);
1716 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001717 }
1718 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001719 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1720 /* now that's a cfgfile list */
1721 argv++; argc--;
1722 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001723 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001724 ha_alert("Cannot load configuration file/directory %s : %s\n",
1725 *argv,
1726 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001727 exit(1);
1728 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001729 argv++; argc--;
1730 }
1731 break;
1732 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 else { /* >=2 args */
1734 argv++; argc--;
1735 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001736 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737
1738 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001739 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001740 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001741 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001743 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001744 free(localpeer);
1745 if ((localpeer = strdup(*argv)) == NULL) {
1746 ha_alert("Cannot allocate memory for local peer.\n");
1747 exit(EXIT_FAILURE);
1748 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001749 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001750 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001751 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001752 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001753 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001754 ha_alert("Cannot load configuration file/directory %s : %s\n",
1755 *argv,
1756 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001757 exit(1);
1758 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001759 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001760 case 'p' : cfg_pidfile = *argv; break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001761 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762 }
1763 }
1764 }
1765 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001766 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767 argv++; argc--;
1768 }
1769
Christopher Faulete3a5e352017-10-24 13:53:54 +02001770 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001771 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001772 | MODE_DIAG | MODE_CHECK_CONDITION));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773
William Lallemand944e6192018-11-21 15:48:31 +01001774 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001775 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001776 global.mode |= MODE_MWORKER_WAIT;
1777 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001778 }
1779
Willy Tarreau26146192021-07-21 10:01:36 +02001780 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1781 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001782 atexit_flag = 1;
1783 atexit(reexec_on_failure);
1784 }
1785
Willy Tarreau576132e2011-09-10 19:26:56 +02001786 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001787 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001788 exit(1);
1789 }
1790
Willy Tarreaubaaee002006-06-26 02:48:02 +02001791 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001792
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001793#ifdef USE_CPU_AFFINITY
1794 {
1795 int i;
Willy Tarreau44ea6312021-06-15 08:57:56 +02001796 ha_cpuset_zero(&cpu_map.proc);
1797 ha_cpuset_zero(&cpu_map.proc_t1);
Willy Tarreau26f42a02021-05-14 08:26:38 +02001798 for (i = 0; i < MAX_THREADS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001799 ha_cpuset_zero(&cpu_map.thread[i]);
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001800 }
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001801 }
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001802#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001803
Amaury Denoyelle11124302021-06-04 18:22:08 +02001804 usermsgs_clr("config");
1805
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001806 if (global.mode & MODE_CHECK_CONDITION) {
1807 int result;
1808
1809 uint32_t err;
1810 const char *errptr;
1811 char *errmsg = NULL;
1812
1813 char *args[MAX_LINE_ARGS+1];
1814 int arg = sizeof(args) / sizeof(*args);
1815 size_t outlen = strlen(check_condition) + 1;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001816 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001817
1818 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001819 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001820 &errptr);
1821
1822 if (err & PARSE_ERR_QUOTE) {
1823 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1824 exit(2);
1825 }
1826
1827 if (err & PARSE_ERR_HEX) {
1828 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1829 exit(2);
1830 }
1831
1832 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1833 ha_alert("Error in condition: Line too long.\n");
1834 exit(2);
1835 }
1836
Willy Tarreauc8194c32021-07-16 16:38:58 +02001837 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001838 ha_alert("Error in condition: Too many words.\n");
1839 exit(2);
1840 }
1841
1842 if (err) {
1843 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1844 exit(2);
1845 }
1846
Willy Tarreauc8194c32021-07-16 16:38:58 +02001847 /* remerge all words into a single expression */
1848 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1849 ;
1850
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001851 result = cfg_eval_condition(args, &errmsg, &errptr);
1852
1853 if (result < 0) {
1854 if (errmsg)
1855 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1856
1857 exit(2);
1858 }
1859
1860 exit(result ? 0 : 1);
1861 }
1862
William Lallemand944e6192018-11-21 15:48:31 +01001863 /* in wait mode, we don't try to read the configuration files */
1864 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001865 char *env_cfgfiles = NULL;
1866 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001867
William Lallemand944e6192018-11-21 15:48:31 +01001868 /* handle cfgfiles that are actually directories */
1869 cfgfiles_expand_directories();
1870
1871 if (LIST_ISEMPTY(&cfg_cfgfiles))
1872 usage(progname);
1873
1874
1875 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1876 int ret;
1877
Christopher Faulet4e366822021-01-12 18:57:38 +01001878 if (env_err == 0) {
1879 if (!memprintf(&env_cfgfiles, "%s%s%s",
1880 (env_cfgfiles ? env_cfgfiles : ""),
1881 (env_cfgfiles ? ";" : ""), wl->s))
1882 env_err = 1;
1883 }
William Lallemand7b302d82019-05-20 11:15:37 +02001884
William Lallemand944e6192018-11-21 15:48:31 +01001885 ret = readcfgfile(wl->s);
1886 if (ret == -1) {
1887 ha_alert("Could not open configuration file %s : %s\n",
1888 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01001889 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001890 exit(1);
1891 }
1892 if (ret & (ERR_ABORT|ERR_FATAL))
1893 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1894 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01001895 if (err_code & ERR_ABORT) {
1896 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001897 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01001898 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001899 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001900
William Lallemand944e6192018-11-21 15:48:31 +01001901 /* do not try to resolve arguments nor to spot inconsistencies when
1902 * the configuration contains fatal errors caused by files not found
1903 * or failed memory allocations.
1904 */
1905 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1906 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01001907 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001908 exit(1);
1909 }
Christopher Faulet4e366822021-01-12 18:57:38 +01001910 if (env_err) {
1911 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1912 exit(1);
1913 }
1914 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1915 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001916
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001917 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001918 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01001919 struct mworker_proc *tmproc;
1920
William Lallemand482f9a92019-04-12 16:15:00 +02001921 setenv("HAPROXY_MWORKER", "1", 1);
1922
William Lallemand16dd1b32018-11-19 18:46:18 +01001923 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1924
William Lallemandf3a86832019-04-01 11:29:58 +02001925 tmproc = calloc(1, sizeof(*tmproc));
William Lallemand16dd1b32018-11-19 18:46:18 +01001926 if (!tmproc) {
1927 ha_alert("Cannot allocate process structures.\n");
1928 exit(EXIT_FAILURE);
1929 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001930 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01001931 tmproc->reloads = 0;
William Lallemand16dd1b32018-11-19 18:46:18 +01001932 tmproc->pid = pid;
1933 tmproc->timestamp = start_date.tv_sec;
1934 tmproc->ipc_fd[0] = -1;
1935 tmproc->ipc_fd[1] = -1;
1936
1937 proc_self = tmproc;
1938
Willy Tarreau2b718102021-04-21 07:32:39 +02001939 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01001940 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001941
Willy Tarreau6185a032021-06-15 08:02:06 +02001942 tmproc = calloc(1, sizeof(*tmproc));
1943 if (!tmproc) {
1944 ha_alert("Cannot allocate process structures.\n");
1945 exit(EXIT_FAILURE);
1946 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001947
Willy Tarreau6185a032021-06-15 08:02:06 +02001948 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
1949 tmproc->pid = -1;
1950 tmproc->reloads = 0;
1951 tmproc->timestamp = -1;
Willy Tarreau6185a032021-06-15 08:02:06 +02001952 tmproc->ipc_fd[0] = -1;
1953 tmproc->ipc_fd[1] = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001954
Willy Tarreau6185a032021-06-15 08:02:06 +02001955 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
1956 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02001957 }
Willy Tarreau6185a032021-06-15 08:02:06 +02001958
1959 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01001960 }
1961 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1962 struct wordlist *it, *c;
1963
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02001964 /* get the info of the children in the env */
1965 if (mworker_env_to_proc_list() < 0) {
1966 exit(EXIT_FAILURE);
1967 }
William Lallemande7361152018-10-26 14:47:36 +02001968
William Lallemand550db6d2018-11-06 17:37:12 +01001969 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02001970
William Lallemand550db6d2018-11-06 17:37:12 +01001971 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02001972 ha_alert("Can't create the master's CLI.\n");
1973 exit(EXIT_FAILURE);
1974 }
William Lallemande7361152018-10-26 14:47:36 +02001975
William Lallemand550db6d2018-11-06 17:37:12 +01001976 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
1977
1978 if (mworker_cli_proxy_new_listener(c->s) < 0) {
1979 ha_alert("Can't create the master's CLI.\n");
1980 exit(EXIT_FAILURE);
1981 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001982 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01001983 free(c->s);
1984 free(c);
1985 }
1986 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001987 }
1988
Eric Salama5ba83352021-03-16 15:11:17 +01001989 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
1990 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
1991 }
1992
Christopher Faulet27c8d202021-10-13 09:50:53 +02001993 /* destroy unreferenced defaults proxies */
1994 proxy_destroy_all_unref_defaults();
1995
Willy Tarreaue90904d2021-02-12 14:08:31 +01001996
Willy Tarreaubb925012009-07-23 13:36:36 +02001997 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02001998 for (px = proxies_list; px; px = px->next) {
1999 struct server *srv;
2000 struct post_proxy_check_fct *ppcf;
2001 struct post_server_check_fct *pscf;
2002
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002003 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002004 continue;
2005
Christopher Fauletc1692962019-08-12 09:51:07 +02002006 list_for_each_entry(pscf, &post_server_check_list, list) {
2007 for (srv = px->srv; srv; srv = srv->next)
2008 err_code |= pscf->fct(srv);
2009 }
2010 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2011 err_code |= ppcf->fct(px);
2012 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002013 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002014 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002015 exit(1);
2016 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002017
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002018 err_code |= pattern_finalize_config();
2019 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2020 ha_alert("Failed to finalize pattern config.\n");
2021 exit(1);
2022 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002023
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002024 if (global.rlimit_memmax_all)
2025 global.rlimit_memmax = global.rlimit_memmax_all;
2026
Willy Tarreaue5733232019-05-22 19:24:06 +02002027#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002028 err_code |= netns_init();
2029 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002030 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002031 exit(1);
2032 }
2033#endif
2034
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002035 /* Apply server states */
2036 apply_server_state();
2037
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002038 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002039 srv_compute_all_admin_states(px);
2040
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002041 /* Apply servers' configured address */
2042 err_code |= srv_init_addr();
2043 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002044 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002045 exit(1);
2046 }
2047
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002048 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2049 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2050 exit(1);
2051 }
2052
Willy Tarreaubaaee002006-06-26 02:48:02 +02002053 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002054 struct peers *pr;
2055 struct proxy *px;
2056
Willy Tarreaubebd2122020-04-15 16:06:11 +02002057 if (warned & WARN_ANY)
2058 qfprintf(stdout, "Warnings were found.\n");
2059
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002060 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002061 if (pr->peers_fe)
2062 break;
2063
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002064 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002065 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002066 break;
2067
Emeric Brunbc5c8212021-08-13 09:32:50 +02002068 if (!px) {
2069 /* We may only have log-forward section */
2070 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002071 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002072 break;
2073 }
2074
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002075 if (pr || px) {
2076 /* At least one peer or one listener has been found */
2077 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002078 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002079 }
2080 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2081 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002082 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002083
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002084 if (global.mode & MODE_DIAG) {
2085 cfg_run_diagnostics();
2086 }
2087
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002088 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002089 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002090
Willy Tarreaue6945732016-12-21 19:57:00 +01002091 list_for_each_entry(pcf, &post_check_list, list) {
2092 err_code |= pcf->fct();
2093 if (err_code & (ERR_ABORT|ERR_FATAL))
2094 exit(1);
2095 }
2096
Willy Tarreaubaaee002006-06-26 02:48:02 +02002097 if (cfg_maxconn > 0)
2098 global.maxconn = cfg_maxconn;
2099
Willy Tarreau4975d142021-03-13 11:00:33 +01002100 if (global.cli_fe)
2101 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002102
2103 if (cfg_peers) {
2104 /* peers also need to bypass global maxconn */
2105 struct peers *p = cfg_peers;
2106
2107 for (p = cfg_peers; p; p = p->next)
2108 if (p->peers_fe)
2109 global.maxsock += p->peers_fe->maxconn;
2110 }
2111
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 if (cfg_pidfile) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002113 free(global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114 global.pidfile = strdup(cfg_pidfile);
2115 }
2116
Willy Tarreaud0256482015-01-15 21:45:22 +01002117 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002118 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2119 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2120 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2121 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002122 *
2123 * If memmax is set, then it depends on which values are set. If
2124 * maxsslconn is set, we use memmax to determine how many cleartext
2125 * connections may be added, and set maxconn to the sum of the two.
2126 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2127 * the remaining amount of memory between memmax and the cleartext
2128 * connections. If neither are set, then it is considered that all
2129 * connections are SSL-capable, and maxconn is computed based on this,
2130 * then maxsslconn accordingly. We need to know if SSL is used on the
2131 * frontends, backends, or both, because when it's used on both sides,
2132 * we need twice the value for maxsslconn, but we only count the
2133 * handshake once since it is not performed on the two sides at the
2134 * same time (frontend-side is terminated before backend-side begins).
2135 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002136 * ssl_handshake_cost during its initialization. In any case, if
2137 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2138 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002139 */
Willy Tarreauac350932019-03-01 15:43:14 +01002140 ideal_maxconn = compute_ideal_maxconn();
2141
Willy Tarreaud0256482015-01-15 21:45:22 +01002142 if (!global.rlimit_memmax) {
2143 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002144 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002145 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2146 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2147 }
2148 }
2149#ifdef USE_OPENSSL
2150 else if (!global.maxconn && !global.maxsslconn &&
2151 (global.ssl_used_frontend || global.ssl_used_backend)) {
2152 /* memmax is set, compute everything automatically. Here we want
2153 * to ensure that all SSL connections will be served. We take
2154 * care of the number of sides where SSL is used, and consider
2155 * the worst case : SSL used on both sides and doing a handshake
2156 * simultaneously. Note that we can't have more than maxconn
2157 * handshakes at a time by definition, so for the worst case of
2158 * two SSL conns per connection, we count a single handshake.
2159 */
2160 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2161 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002162 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002163
2164 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2165 mem -= global.maxzlibmem;
2166 mem = mem * MEM_USABLE_RATIO;
2167
Willy Tarreau304e17e2020-03-10 17:54:54 +01002168 /* Principle: we test once to set maxconn according to the free
2169 * memory. If it results in values the system rejects, we try a
2170 * second time by respecting rlim_fd_max. If it fails again, we
2171 * go back to the initial value and will let the final code
2172 * dealing with rlimit report the error. That's up to 3 attempts.
2173 */
2174 do {
2175 global.maxconn = mem /
2176 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2177 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2178 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002179
Willy Tarreau304e17e2020-03-10 17:54:54 +01002180 if (retried == 1)
2181 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2182 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002183#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002184 if (global.maxconn > SYSTEM_MAXCONN)
2185 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002186#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002187 global.maxsslconn = sides * global.maxconn;
2188
2189 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2190 break;
2191 } while (retried++ < 2);
2192
Willy Tarreaud0256482015-01-15 21:45:22 +01002193 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2194 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2195 global.maxconn, global.maxsslconn);
2196 }
2197 else if (!global.maxsslconn &&
2198 (global.ssl_used_frontend || global.ssl_used_backend)) {
2199 /* memmax and maxconn are known, compute maxsslconn automatically.
2200 * maxsslconn being forced, we don't know how many of it will be
2201 * on each side if both sides are being used. The worst case is
2202 * when all connections use only one SSL instance because
2203 * handshakes may be on two sides at the same time.
2204 */
2205 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2206 int64_t mem = global.rlimit_memmax * 1048576ULL;
2207 int64_t sslmem;
2208
2209 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2210 mem -= global.maxzlibmem;
2211 mem = mem * MEM_USABLE_RATIO;
2212
Willy Tarreau87b09662015-04-03 00:22:06 +02002213 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002214 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2215 global.maxsslconn = round_2dig(global.maxsslconn);
2216
2217 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002218 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2219 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2220 "without SSL is %d, but %d was found and SSL is in use.\n",
2221 global.rlimit_memmax,
2222 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2223 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002224 exit(1);
2225 }
2226
2227 if (global.maxsslconn > sides * global.maxconn)
2228 global.maxsslconn = sides * global.maxconn;
2229
2230 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2231 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2232 }
2233#endif
2234 else if (!global.maxconn) {
2235 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2236 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2237 int64_t mem = global.rlimit_memmax * 1048576ULL;
2238 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002239 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002240
2241 if (global.ssl_used_frontend || global.ssl_used_backend)
2242 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2243
2244 mem -= global.maxzlibmem;
2245 mem = mem * MEM_USABLE_RATIO;
2246
2247 clearmem = mem;
2248 if (sides)
2249 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2250
Willy Tarreau304e17e2020-03-10 17:54:54 +01002251 /* Principle: we test once to set maxconn according to the free
2252 * memory. If it results in values the system rejects, we try a
2253 * second time by respecting rlim_fd_max. If it fails again, we
2254 * go back to the initial value and will let the final code
2255 * dealing with rlimit report the error. That's up to 3 attempts.
2256 */
2257 do {
2258 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2259 if (retried == 1)
2260 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2261 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002262#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002263 if (global.maxconn > SYSTEM_MAXCONN)
2264 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002265#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002266
Willy Tarreau304e17e2020-03-10 17:54:54 +01002267 if (clearmem <= 0 || !global.maxconn) {
2268 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2269 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2270 "is %d, but %d was found.\n",
2271 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002272 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002273 global.maxsslconn);
2274 exit(1);
2275 }
2276
2277 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2278 break;
2279 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002280
2281 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2282 if (sides && global.maxsslconn > sides * global.maxconn) {
2283 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2284 "to be limited to %d. Better reduce global.maxsslconn to get more "
2285 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2286 }
2287 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2288 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002289 }
2290
Willy Tarreaua409f302020-03-10 17:08:53 +01002291 global.maxsock = compute_ideal_maxsock(global.maxconn);
2292 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002293 if (!global.maxpipes)
2294 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295
Olivier Houchard88698d92019-04-16 19:07:22 +02002296 /* update connection pool thresholds */
2297 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2298 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2299
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002300 proxy_adjust_all_maxconn();
2301
Willy Tarreau1db37712007-06-03 17:16:49 +02002302 if (global.tune.maxpollevents <= 0)
2303 global.tune.maxpollevents = MAX_POLL_EVENTS;
2304
Willy Tarreau060a7612021-03-10 11:06:26 +01002305 if (global.tune.runqueue_depth <= 0) {
2306 /* tests on various thread counts from 1 to 64 have shown an
2307 * optimal queue depth following roughly 1/sqrt(threads).
2308 */
2309 int s = my_flsl(global.nbthread);
2310 s += (global.nbthread / s); // roughly twice the sqrt.
2311 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2312 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002313
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002314 if (global.tune.recv_enough == 0)
2315 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2316
Willy Tarreau27a674e2009-08-17 07:23:33 +02002317 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2318 global.tune.maxrewrite = global.tune.bufsize / 2;
2319
Amaury Denoyelle11124302021-06-04 18:22:08 +02002320 usermsgs_clr(NULL);
2321
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2323 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002324 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002325 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2326 }
2327
William Lallemand095ba4c2017-06-01 17:38:50 +02002328 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002329 /* command line daemon mode inhibits foreground and debug modes mode */
2330 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002331 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002332 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002333
2334 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002335
William Lallemand095ba4c2017-06-01 17:38:50 +02002336 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002337 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002338 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339 }
2340
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002341 if (global.nbthread < 1)
2342 global.nbthread = 1;
2343
Christopher Faulet3ef26392017-08-29 16:46:57 +02002344 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002345 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002346 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002347 exit(1);
2348 }
2349
Christopher Faulet96d44832017-11-14 22:02:30 +01002350 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002351 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002352 exit(1);
2353 }
2354
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002355 /*
2356 * Note: we could register external pollers here.
2357 * Built-in pollers have been registered before main().
2358 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002359
Willy Tarreau43b78992009-01-25 15:42:27 +01002360 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002361 disable_poller("kqueue");
2362
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002363 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2364 disable_poller("evports");
2365
Willy Tarreau43b78992009-01-25 15:42:27 +01002366 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002367 disable_poller("epoll");
2368
Willy Tarreau43b78992009-01-25 15:42:27 +01002369 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002370 disable_poller("poll");
2371
Willy Tarreau43b78992009-01-25 15:42:27 +01002372 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002373 disable_poller("select");
2374
2375 /* Note: we could disable any poller by name here */
2376
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002377 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002378 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002379 fprintf(stderr, "\n");
2380 list_filters(stderr);
2381 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002382
Willy Tarreau4f60f162007-04-08 16:39:58 +02002383 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002384 ha_alert("No polling mechanism available.\n"
2385 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2386 " is too low on this platform to support maxconn and the number of listeners\n"
2387 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2388 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2389 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2390 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2391 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2392 " check build settings using 'haproxy -vv'.\n\n",
2393 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002394 exit(1);
2395 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002396 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2397 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002398 }
2399
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002400 if (!global.node)
2401 global.node = strdup(hostname);
2402
Willy Tarreau02b092f2020-10-07 18:36:54 +02002403 /* stop disabled proxies */
2404 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002405 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002406 stop_proxy(px);
2407 }
2408
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002409 if (!hlua_post_init())
2410 exit(1);
Thomas Holmes6abded42015-05-12 16:23:58 +01002411
Maxime de Roucy0f503922016-05-13 23:52:55 +02002412 free(err_msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413}
2414
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002415void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002416{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002417 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002418 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002419 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002420 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002421 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002422 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002423 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002424 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002425 struct per_thread_init_fct *tif, *tifb;
2426 struct per_thread_deinit_fct *tdf, *tdfb;
2427 struct per_thread_alloc_fct *taf, *tafb;
2428 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002429 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002430 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002431 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002432 int cur_fd;
2433
2434 /* At this point the listeners state is weird:
2435 * - most listeners are still bound and referenced in their protocol
2436 * - some might be zombies that are not in their proto anymore, but
2437 * still appear in their proxy's listeners with a valid FD.
2438 * - some might be stopped and still appear in their proxy as FD #-1
2439 * - among all of them, some might be inherited hence shared and we're
2440 * not allowed to pause them or whatever, we must just close them.
2441 * - finally some are not listeners (pipes, logs, stdout, etc) and
2442 * must be left intact.
2443 *
2444 * The safe way to proceed is to unbind (and close) whatever is not yet
2445 * unbound so that no more receiver/listener remains alive. Then close
2446 * remaining listener FDs, which correspond to zombie listeners (those
2447 * belonging to disabled proxies that were in another process).
2448 * objt_listener() would be cleaner here but not converted yet.
2449 */
2450 protocol_unbind_all();
2451
2452 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002453 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002454 continue;
2455
Willy Tarreaua74cb382020-10-15 21:29:49 +02002456 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002457 struct listener *l = fdtab[cur_fd].owner;
2458
2459 BUG_ON(l->state != LI_INIT);
2460 unbind_listener(l);
2461 }
2462 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002463
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002464 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002466 /* build a list of unique uri_auths */
2467 if (!ua)
2468 ua = p->uri_auth;
2469 else {
2470 /* check if p->uri_auth is unique */
2471 for (uap = ua; uap; uap=uap->next)
2472 if (uap == p->uri_auth)
2473 break;
2474
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002475 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002476 /* add it, if it is */
2477 p->uri_auth->next = ua;
2478 ua = p->uri_auth;
2479 }
William Lallemand0f99e342011-10-12 17:50:54 +02002480 }
2481
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002482 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002484 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002485 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002486
Christopher Faulet27c8d202021-10-13 09:50:53 +02002487 /* destroy all referenced defaults proxies */
2488 proxy_destroy_all_unref_defaults();
2489
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002490 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002491 struct stat_scope *scope, *scopep;
2492
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002493 uap = ua;
2494 ua = ua->next;
2495
Willy Tarreaua534fea2008-08-03 12:19:50 +02002496 free(uap->uri_prefix);
2497 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002498 free(uap->node);
2499 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002500
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002501 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002502 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002503
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002504 scope = uap->scope;
2505 while (scope) {
2506 scopep = scope;
2507 scope = scope->next;
2508
2509 free(scopep->px_id);
2510 free(scopep);
2511 }
2512
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002513 free(uap);
2514 }
2515
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002516 userlist_free(userlist);
2517
David Carlier834cb2e2015-09-25 12:02:25 +01002518 cfg_unregister_sections();
2519
Christopher Faulet0132d062017-07-26 15:33:35 +02002520 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002521
Willy Tarreau05554e62016-12-21 20:46:26 +01002522 list_for_each_entry(pdf, &post_deinit_list, list)
2523 pdf->fct();
2524
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002525 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002526 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002527 ha_free(&global.chroot);
2528 ha_free(&global.pidfile);
2529 ha_free(&global.node);
2530 ha_free(&global.desc);
2531 ha_free(&oldpids);
2532 ha_free(&old_argv);
2533 ha_free(&localpeer);
2534 ha_free(&global.server_state_base);
2535 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002536 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002537 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002538
William Lallemand0f99e342011-10-12 17:50:54 +02002539 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002540 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002541 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002542 free(log);
2543 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002544 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002545 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002546 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002547 free(wl);
2548 }
2549
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002550 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2551 if (bol->must_free)
2552 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002553 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002554 free(bol);
2555 }
2556
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002557 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002558 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002559 free(pxdf);
2560 }
2561
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002562 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002563 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002564 free(pdf);
2565 }
2566
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002567 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002568 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002569 free(srvdf);
2570 }
2571
Tim Duesterhusfc854942020-09-10 19:46:42 +02002572 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002573 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002574 free(pcf);
2575 }
2576
Tim Duesterhus34bef072020-07-04 11:49:50 +02002577 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002578 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002579 free(pscf);
2580 }
2581
Tim Duesterhus53508d62020-09-10 19:46:40 +02002582 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002583 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002584 free(ppcf);
2585 }
2586
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002587 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002588 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002589 free(tif);
2590 }
2591
2592 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002593 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002594 free(tdf);
2595 }
2596
2597 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002598 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002599 free(taf);
2600 }
2601
2602 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002603 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002604 free(tff);
2605 }
2606
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002607 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002608 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002609 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610} /* end deinit() */
2611
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002612__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002613{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002614 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002615 deinit();
2616 exit(status);
2617}
William Lallemand72160322018-11-06 17:37:16 +01002618
Willy Tarreau918ff602011-07-25 16:33:49 +02002619/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002620void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002621{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002622 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002623
Willy Tarreau55542642021-10-08 09:33:24 +02002624 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002625 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002626 wake_expired_tasks();
2627
William Lallemand1aab50b2018-06-07 09:46:01 +02002628 /* check if we caught some signals and process them in the
2629 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002630 if (signal_queue_len && tid == 0) {
2631 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002632 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002633 }
2634
2635 /* Process a few tasks */
2636 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002637
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002638 /* also stop if we failed to cleanly stop all tasks */
2639 if (killed > 1)
2640 break;
2641
Willy Tarreau10146c92015-04-13 20:44:19 +02002642 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002643 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002644 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002645 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002646 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002647 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2648 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002649 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002650 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002651 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002652 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002653 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002654 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002655
Willy Tarreau4f46a352020-03-23 09:27:28 +01002656 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002657 int i;
2658
2659 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002660 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002661 if (!(stopping_thread_mask & tid_bit)) {
2662 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2663 wake = 1;
2664 }
2665
Willy Tarreau1db42732021-04-06 11:44:07 +02002666 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002667 /* notify all threads that stopping was just set */
2668 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002669 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002670 wake_thread(i);
2671 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002672 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002673
2674 /* stop when there's nothing left to do */
2675 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002676 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2677 /* wake all threads waiting on jobs==0 */
2678 for (i = 0; i < global.nbthread; i++)
2679 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2680 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002681 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002682 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002683 }
2684
Willy Tarreauc49ba522019-12-11 08:12:23 +01002685 /* If we have to sleep, measure how long */
2686 next = wake ? TICK_ETERNITY : next_timer_expiry();
2687
Willy Tarreau58b458d2008-06-29 22:40:23 +02002688 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002689 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002690
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002691 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002692 }
2693}
2694
Christopher Faulet1d17c102017-08-29 15:38:48 +02002695static void *run_thread_poll_loop(void *data)
2696{
Willy Tarreau082b6282019-05-22 14:42:12 +02002697 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002698 struct per_thread_init_fct *ptif;
2699 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002700 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002701 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002702 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2703 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002704
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002705 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002706 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002707 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002708
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002709 /* Now, initialize one thread init at a time. This is better since
2710 * some init code is a bit tricky and may release global resources
2711 * after reallocating them locally. This will also ensure there is
2712 * no race on file descriptors allocation.
2713 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002714#ifdef USE_THREAD
2715 pthread_mutex_lock(&init_mutex);
2716#endif
2717 /* The first thread must set the number of threads left */
2718 if (!init_left)
2719 init_left = global.nbthread;
2720 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002721
Willy Tarreau55542642021-10-08 09:33:24 +02002722 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002723
Willy Tarreau082b6282019-05-22 14:42:12 +02002724 /* per-thread alloc calls performed here are not allowed to snoop on
2725 * other threads, so they are free to initialize at their own rhythm
2726 * as long as they act as if they were alone. None of them may rely
2727 * on resources initialized by the other ones.
2728 */
2729 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2730 if (!ptaf->fct()) {
2731 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002732#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002733 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002734#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002735 exit(1);
2736 }
2737 }
2738
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002739 /* per-thread init calls performed here are not allowed to snoop on
2740 * other threads, so they are free to initialize at their own rhythm
2741 * as long as they act as if they were alone.
2742 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002743 list_for_each_entry(ptif, &per_thread_init_list, list) {
2744 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002745 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002746#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002747 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002748#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002749 exit(1);
2750 }
2751 }
2752
Willy Tarreau71092822019-06-10 09:51:04 +02002753 /* enabling protocols will result in fd_insert() calls to be performed,
2754 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002755 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002756 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002757 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002758 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002759
Willy Tarreau34a150c2019-06-11 09:16:41 +02002760#ifdef USE_THREAD
2761 pthread_cond_broadcast(&init_cond);
2762 pthread_mutex_unlock(&init_mutex);
2763
2764 /* now wait for other threads to finish starting */
2765 pthread_mutex_lock(&init_mutex);
2766 while (init_left)
2767 pthread_cond_wait(&init_cond, &init_mutex);
2768 pthread_mutex_unlock(&init_mutex);
2769#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002770
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002771#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2772 /* Let's refrain from using setuid executables. This way the impact of
2773 * an eventual vulnerability in a library remains limited. It may
2774 * impact external checks but who cares about them anyway ? In the
2775 * worst case it's possible to disable the option. Obviously we do this
2776 * in workers only. We can't hard-fail on this one as it really is
2777 * implementation dependent though we're interested in feedback, hence
2778 * the warning.
2779 */
2780 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2781 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002782 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 +01002783 ha_warning("Failed to disable setuid, please report to developers with detailed "
2784 "information about your operating system. You can silence this warning "
2785 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2786 }
2787 }
2788#endif
2789
Willy Tarreaud96f1122019-12-03 07:07:36 +01002790#if defined(RLIMIT_NPROC)
2791 /* all threads have started, it's now time to prevent any new thread
2792 * or process from starting. Obviously we do this in workers only. We
2793 * can't hard-fail on this one as it really is implementation dependent
2794 * though we're interested in feedback, hence the warning.
2795 */
2796 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2797 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2798 static int warn_fail;
2799
Willy Tarreau18515722021-04-06 11:57:41 +02002800 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002801 ha_warning("Failed to disable forks, please report to developers with detailed "
2802 "information about your operating system. You can silence this warning "
2803 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2804 }
2805 }
2806#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002807 run_poll_loop();
2808
2809 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2810 ptdf->fct();
2811
Willy Tarreau082b6282019-05-22 14:42:12 +02002812 list_for_each_entry(ptff, &per_thread_free_list, list)
2813 ptff->fct();
2814
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002815#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002816 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002817 if (tid > 0)
2818 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002819#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002820 return NULL;
2821}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002822
William Dauchyf9af9d72019-11-17 15:47:16 +01002823/* set uid/gid depending on global settings */
2824static void set_identity(const char *program_name)
2825{
2826 if (global.gid) {
2827 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2828 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2829 " without 'uid'/'user' is generally useless.\n", program_name);
2830
2831 if (setgid(global.gid) == -1) {
2832 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2833 protocol_unbind_all();
2834 exit(1);
2835 }
2836 }
2837
2838 if (global.uid && setuid(global.uid) == -1) {
2839 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2840 protocol_unbind_all();
2841 exit(1);
2842 }
2843}
2844
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845int main(int argc, char **argv)
2846{
2847 int err, retry;
2848 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002849 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02002850 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2851
2852 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2853 if (intovf + 0x7FFFFFFF >= intovf) {
2854 fprintf(stderr,
2855 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2856 "The source code was miscompiled by the compiler, which usually indicates that\n"
2857 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2858 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2859 "and INSTALL files to decide on the best way to pass your local build options.\n"
2860 "\nBuild options :"
2861#ifdef BUILD_TARGET
2862 "\n TARGET = " BUILD_TARGET
2863#endif
2864#ifdef BUILD_CPU
2865 "\n CPU = " BUILD_CPU
2866#endif
2867#ifdef BUILD_CC
2868 "\n CC = " BUILD_CC
2869#endif
2870#ifdef BUILD_CFLAGS
2871 "\n CFLAGS = " BUILD_CFLAGS
2872#endif
2873#ifdef BUILD_OPTIONS
2874 "\n OPTIONS = " BUILD_OPTIONS
2875#endif
2876#ifdef BUILD_DEBUG
2877 "\n DEBUG = " BUILD_DEBUG
2878#endif
2879 "\n\n");
2880 return 1;
2881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002883 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002884
Willy Tarreaubf696402019-03-01 10:09:28 +01002885 /* take a copy of initial limits before we possibly change them */
2886 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02002887
2888 if (limit.rlim_max == RLIM_INFINITY)
2889 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01002890 rlim_fd_cur_at_boot = limit.rlim_cur;
2891 rlim_fd_max_at_boot = limit.rlim_max;
2892
Willy Tarreau5794fb02018-11-25 18:43:29 +01002893 /* process all initcalls in order of potential dependency */
2894 RUN_INITCALLS(STG_PREPARE);
2895 RUN_INITCALLS(STG_LOCK);
2896 RUN_INITCALLS(STG_ALLOC);
2897 RUN_INITCALLS(STG_POOL);
2898 RUN_INITCALLS(STG_REGISTER);
2899 RUN_INITCALLS(STG_INIT);
2900
Emeric Bruncf20bf12010-10-22 16:06:11 +02002901 init(argc, argv);
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002902 signal_register_fct(SIGQUIT, dump, SIGQUIT);
2903 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
2904 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02002905 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002906
Willy Tarreaue437c442010-03-17 18:02:46 +01002907 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
2908 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
2909 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002910 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002911 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912
Willy Tarreaudc23a922011-02-16 11:10:36 +01002913 /* ulimits */
2914 if (!global.rlimit_nofile)
2915 global.rlimit_nofile = global.maxsock;
2916
2917 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01002918 limit.rlim_cur = global.rlimit_nofile;
2919 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
2920
Willy Tarreaudc23a922011-02-16 11:10:36 +01002921 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02002922 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002923 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2924 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
2925 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002926 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002927 }
2928 else {
2929 /* try to set it to the max possible at least */
2930 limit.rlim_cur = limit.rlim_max;
2931 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
2932 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02002933
William Dauchya5194602020-03-28 19:29:58 +01002934 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002935 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
2936 global.rlimit_nofile = limit.rlim_cur;
2937 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01002938 }
2939 }
2940
2941 if (global.rlimit_memmax) {
2942 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01002943 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01002944#ifdef RLIMIT_AS
2945 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002946 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2947 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2948 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002949 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002950 }
2951 else
William Dauchya5194602020-03-28 19:29:58 +01002952 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002953 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002954 }
2955#else
2956 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002957 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2958 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2959 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002960 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002961 }
2962 else
William Dauchya5194602020-03-28 19:29:58 +01002963 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002964 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002965 }
2966#endif
2967 }
2968
Olivier Houchardf73629d2017-04-05 22:33:04 +02002969 if (old_unixsocket) {
William Lallemand85b0bd92017-06-01 17:38:53 +02002970 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02002971 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002972 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02002973 if (!(global.mode & MODE_MWORKER))
2974 exit(1);
2975 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02002976 }
2977 }
William Lallemand85b0bd92017-06-01 17:38:53 +02002978 get_cur_unixsocket();
2979
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 /* We will loop at most 100 times with 10 ms delay each time.
2981 * That's at most 1 second. We only send a signal to old pids
2982 * if we cannot grab at least one port.
2983 */
2984 retry = MAX_START_RETRIES;
2985 err = ERR_NONE;
2986 while (retry >= 0) {
2987 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02002988 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01002989 /* exit the loop on no error or fatal error */
2990 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02002992 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 break;
2994
2995 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
2996 * listening sockets. So on those platforms, it would be wiser to
2997 * simply send SIGUSR1, which will not be undoable.
2998 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02002999 if (tell_old_pids(SIGTTOU) == 0) {
3000 /* no need to wait if we can't contact old pids */
3001 retry = 0;
3002 continue;
3003 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 /* give some time to old processes to stop listening */
3005 w.tv_sec = 0;
3006 w.tv_usec = 10*1000;
3007 select(0, NULL, NULL, NULL, &w);
3008 retry--;
3009 }
3010
Willy Tarreaue91bff22020-09-02 11:11:43 +02003011 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003012 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003013 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003014 if (retry != MAX_START_RETRIES && nb_oldpids) {
3015 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003017 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003018 exit(1);
3019 }
3020
William Lallemand944e6192018-11-21 15:48:31 +01003021 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003022 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 /* Note: we don't have to send anything to the old pids because we
3024 * never stopped them. */
3025 exit(1);
3026 }
3027
Willy Tarreaue91bff22020-09-02 11:11:43 +02003028 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003029 * the previous process gave us, we don't need them anymore
3030 */
3031 while (xfer_sock_list != NULL) {
3032 struct xfer_sock_list *tmpxfer = xfer_sock_list->next;
3033 close(xfer_sock_list->fd);
3034 free(xfer_sock_list->iface);
3035 free(xfer_sock_list->namespace);
3036 free(xfer_sock_list);
3037 xfer_sock_list = tmpxfer;
3038 }
Willy Tarreaudd815982007-10-16 12:25:14 +02003039
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003041 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3042 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044 /* MODE_QUIET can inhibit alerts and warnings below this line */
3045
PiBa-NL149a81a2017-12-25 21:03:31 +01003046 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3047 /* either stdin/out/err are already closed or should stay as they are. */
3048 if ((global.mode & MODE_DAEMON)) {
3049 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3050 global.mode &= ~MODE_VERBOSE;
3051 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3052 }
3053 } else {
3054 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3055 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003056 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003057 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 }
3059
3060 /* open log & pid files before the chroot */
William Lallemand80293002017-11-06 11:00:03 +01003061 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003062 unlink(global.pidfile);
3063 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3064 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003065 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 if (nb_oldpids)
3067 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003068 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 exit(1);
3070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 }
3072
Willy Tarreaub38651a2007-03-24 17:24:39 +01003073 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003074 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3075 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003076 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003077 exit(1);
3078 }
3079
Jackie Tapia749f74c2020-07-22 18:59:40 -05003080 /* If the user is not root, we'll still let them try the configuration
3081 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003082 */
3083 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003084 ha_warning("[%s.main()] Some options which require full privileges"
3085 " might not work well.\n"
3086 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003087
William Lallemand095ba4c2017-06-01 17:38:50 +02003088 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3089
3090 /* chroot if needed */
3091 if (global.chroot != NULL) {
3092 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003093 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003094 if (nb_oldpids)
3095 tell_old_pids(SIGTTIN);
3096 protocol_unbind_all();
3097 exit(1);
3098 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003099 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003100 }
3101
William Lallemand944e6192018-11-21 15:48:31 +01003102 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003103 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104
William Lallemand27edc4b2019-05-07 17:49:33 +02003105 /* send a SIGTERM to workers who have a too high reloads number */
3106 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3107 mworker_kill_max_reloads(SIGTERM);
3108
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 /* Note that any error at this stage will be fatal because we will not
3110 * be able to restart the old pids.
3111 */
3112
William Dauchyf9af9d72019-11-17 15:47:16 +01003113 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3114 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003115
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 /* check ulimits */
3117 limit.rlim_cur = limit.rlim_max = 0;
3118 getrlimit(RLIMIT_NOFILE, &limit);
3119 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003120 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3121 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3122 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3123 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3124 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003125 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003126 }
3127 else
3128 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003129 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003130 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3131 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 }
3133
William Lallemand944e6192018-11-21 15:48:31 +01003134 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003136 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003137 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138
William Lallemand095ba4c2017-06-01 17:38:50 +02003139 /*
3140 * if daemon + mworker: must fork here to let a master
3141 * process live in background before forking children
3142 */
William Lallemand73b85e72017-06-01 17:38:51 +02003143
3144 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3145 && (global.mode & MODE_MWORKER)
3146 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003147 ret = fork();
3148 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003149 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003150 protocol_unbind_all();
3151 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003152 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003153 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003154 } else /* change the process group ID in the child (master process) */
3155 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003156 }
William Lallemande20b6a62017-06-01 17:38:55 +02003157
William Lallemande20b6a62017-06-01 17:38:55 +02003158
William Lallemanddeed7802017-11-06 11:00:04 +01003159 /* if in master-worker mode, write the PID of the father */
3160 if (global.mode & MODE_MWORKER) {
3161 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003162 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003163 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003164 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003165 }
3166
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003168 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003169 if (global.mode & MODE_MWORKER)
3170 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003171
3172 ret = fork();
3173 if (ret < 0) {
3174 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3175 protocol_unbind_all();
3176 exit(1); /* there has been an error */
3177 }
3178 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003179 /* This one must not be exported, it's internal! */
3180 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003181 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003182 }
3183 else { /* parent here */
3184 in_parent = 1;
3185
William Lallemand944e6192018-11-21 15:48:31 +01003186 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3187 char pidstr[100];
3188 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003189 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003190 }
3191 if (global.mode & MODE_MWORKER) {
3192 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003193
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003194 ha_notice("New worker #%d (%d) forked\n", 1, ret);
William Lallemand944e6192018-11-21 15:48:31 +01003195 /* find the right mworker_proc */
3196 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003197 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003198 child->timestamp = now.tv_sec;
3199 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003200 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003201 break;
3202 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003203 }
3204 }
William Lallemand944e6192018-11-21 15:48:31 +01003205 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003206
William Lallemand944e6192018-11-21 15:48:31 +01003207 } else {
3208 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003209 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003210 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003211
3212#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003213 if (!in_parent && ha_cpuset_count(&cpu_map.proc)) { /* only do this if the process has a CPU map */
Olivier Houchard97148f62017-08-16 17:29:11 +02003214
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003215#ifdef __FreeBSD__
Willy Tarreau44ea6312021-06-15 08:57:56 +02003216 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003217 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
David Carlier2d0493a2020-12-02 21:14:51 +00003218#elif defined(__linux__) || defined(__DragonFly__)
Willy Tarreau44ea6312021-06-15 08:57:56 +02003219 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003220 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003221#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003222 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003223#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003225 if (pidfd >= 0) {
3226 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3227 close(pidfd);
3228 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003229
3230 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003231 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232
Willy Tarreaud67ff342021-06-15 07:58:09 +02003233 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003234 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003235
3236 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3237 (global.mode & MODE_DAEMON)) {
3238 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003239 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3240 stdio_quiet(-1);
3241
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003242 global.mode &= ~MODE_VERBOSE;
3243 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003244 }
3245
William Lallemandb3f2be32018-09-11 10:06:18 +02003246 mworker_loop();
William Lallemand1499b9b2017-06-07 15:04:47 +02003247 /* should never get there */
3248 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003249 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003250#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003251 ssl_free_dh();
3252#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003253 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003254 }
3255
William Lallemandcb11fd22017-06-01 17:38:52 +02003256 /* child must never use the atexit function */
3257 atexit_flag = 0;
3258
William Lallemandbc193052018-09-11 10:06:26 +02003259 /* close useless master sockets */
3260 if (global.mode & MODE_MWORKER) {
3261 struct mworker_proc *child, *it;
3262 master = 0;
3263
William Lallemand309dc9a2018-10-26 14:47:45 +02003264 mworker_cli_proxy_stop();
3265
William Lallemandbc193052018-09-11 10:06:26 +02003266 /* free proc struct of other processes */
3267 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003268 /* close the FD of the master side for all
3269 * workers, we don't need to close the worker
3270 * side of other workers since it's done with
3271 * the bind_proc */
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003272 if (child->ipc_fd[0] >= 0)
3273 close(child->ipc_fd[0]);
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003274 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003275 child->reloads == 0) {
3276 /* keep this struct if this is our pid */
3277 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003278 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003279 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003280 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003281 mworker_free_child(child);
3282 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003283 }
3284 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003285
William Lallemande1340412017-12-28 16:09:36 +01003286 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3287 devnullfd = open("/dev/null", O_RDWR, 0);
3288 if (devnullfd < 0) {
3289 ha_alert("Cannot open /dev/null\n");
3290 exit(EXIT_FAILURE);
3291 }
3292 }
3293
William Lallemand095ba4c2017-06-01 17:38:50 +02003294 /* Must chroot and setgid/setuid in the children */
3295 /* chroot if needed */
3296 if (global.chroot != NULL) {
3297 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003298 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003299 if (nb_oldpids)
3300 tell_old_pids(SIGTTIN);
3301 protocol_unbind_all();
3302 exit(1);
3303 }
3304 }
3305
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003306 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003307 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003308
William Lallemand7f80eb22017-05-26 18:19:55 +02003309 /* pass through every cli socket, and check if it's bound to
3310 * the current process and if it exposes listeners sockets.
3311 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3312 * */
3313
Willy Tarreau4975d142021-03-13 11:00:33 +01003314 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003315 struct bind_conf *bind_conf;
3316
Willy Tarreau4975d142021-03-13 11:00:33 +01003317 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003318 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003319 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3320 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003321 }
3322 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003323 }
3324
William Lallemand2e8fad92018-11-13 16:18:23 +01003325 /*
3326 * This is only done in daemon mode because we might want the
3327 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3328 * we should now close the 3 first FDs to ensure that we can
3329 * detach from the TTY. We MUST NOT do it in other cases since
3330 * it would have already be done, and 0-2 would have been
3331 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003333 if ((global.mode & MODE_DAEMON) &&
3334 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003336 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003337 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003338 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3339 }
3340 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003341 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3342 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003343 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003344 }
3345
William Dauchye039f262019-11-17 15:47:15 +01003346 /* try our best to re-enable core dumps depending on system capabilities.
3347 * What is addressed here :
3348 * - remove file size limits
3349 * - remove core size limits
3350 * - mark the process dumpable again if it lost it due to user/group
3351 */
3352 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3353 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3354
3355#if defined(RLIMIT_FSIZE)
3356 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3357 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3358 ha_alert("[%s.main()] Failed to set the raise the maximum "
3359 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003360 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003361 }
3362 else
3363 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003364 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003365 }
3366#endif
3367
3368#if defined(RLIMIT_CORE)
3369 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3370 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3371 ha_alert("[%s.main()] Failed to set the raise the core "
3372 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003373 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003374 }
3375 else
3376 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003377 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003378 }
3379#endif
3380
3381#if defined(USE_PRCTL)
3382 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3383 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3384 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003385#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003386 {
3387 int traceable = PROC_TRACE_CTL_ENABLE;
3388 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3389 ha_warning("[%s.main()] Failed to set the traceable flag, "
3390 "no core will be dumped.\n", argv[0]);
3391 }
William Dauchye039f262019-11-17 15:47:15 +01003392#endif
3393 }
3394
Christopher Faulete3a5e352017-10-24 13:53:54 +02003395 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003396 reset_usermsgs_ctx();
3397
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003398 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003399 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003400
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003401 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003402 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003403
3404 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003405 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003406
3407 /* wait for all threads to terminate */
3408 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003409
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003410 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411}
3412
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413/*
3414 * Local variables:
3415 * c-indent-level: 8
3416 * c-basic-offset: 8
3417 * End:
3418 */