blob: 892d821944880b3b16cf30df205a0aa4b22d5a9e [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 Tarreau2454d6e2022-02-01 18:06:59 +01003 * Copyright 2000-2022 Willy Tarreau <willy@haproxy.org>.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
Ilya Shipitsin46a030c2020-07-05 16:36:08 +050010 * Please refer to RFC7230 - RFC7235 information about HTTP protocol, and
11 * RFC6265 for information about cookies usage. More generally, the IETF HTTP
Willy Tarreaubaaee002006-06-26 02:48:02 +020012 * Working Group's web site should be consulted for protocol related changes :
13 *
14 * http://ftp.ics.uci.edu/pub/ietf/http/
15 *
16 * Pending bugs (may be not fixed because never reproduced) :
17 * - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
18 * the proxy to terminate (no core) if the client breaks the connection during
19 * the response. Seen on 1.1.8pre4, but never reproduced. May not be related to
20 * the snprintf() bug since requests were simple (GET / HTTP/1.0), but may be
21 * related to missing setsid() (fixed in 1.1.15)
22 * - a proxy with an invalid config will prevent the startup even if disabled.
23 *
24 * ChangeLog has moved to the CHANGELOG file.
25 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020026 */
27
David Carlier7ece0962015-12-08 21:43:09 +000028#define _GNU_SOURCE
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include <ctype.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020034#include <dirent.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020035#include <sys/stat.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <sys/time.h>
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <netinet/tcp.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <signal.h>
46#include <stdarg.h>
47#include <sys/resource.h>
Tim Duesterhusdfad6a42020-04-18 16:02:47 +020048#include <sys/utsname.h>
Marc-Antoine Perennou992709b2013-02-12 10:53:52 +010049#include <sys/wait.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <time.h>
51#include <syslog.h>
Michael Schererab012dd2013-01-12 18:35:19 +010052#include <grp.h>
Willy 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>
Frédéric Lécaille1d96d6e2022-05-23 16:38:14 +0200118#include <haproxy/quic_tp-t.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200119#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200120#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200121#include <haproxy/pool.h>
122#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200123#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200124#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200125#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200126#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200127#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200128#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200129#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200130#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200131#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200132#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200133#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200134#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200135#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200136#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200137#include <haproxy/time.h>
138#include <haproxy/tools.h>
139#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200140#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200141#include <haproxy/version.h>
Frédéric Lécaille92862102022-05-20 16:29:10 +0200142#include <haproxy/xprt_quic-t.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200143
Willy Tarreaubaaee002006-06-26 02:48:02 +0200144
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100145/* array of init calls for older platforms */
146DECLARE_INIT_STAGES;
147
Willy Tarreauf4596402021-04-10 16:53:05 +0200148/* create a read_mostly section to hold variables which are accessed a lot
149 * but which almost never change. The purpose is to isolate them in their
150 * own cache lines where they don't risk to be perturbated by write accesses
151 * to neighbor variables. We need to create an empty aligned variable for
152 * this. The fact that the variable is of size zero means that it will be
153 * eliminated at link time if no other variable uses it, but alignment will
154 * be respected.
155 */
156empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
157
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200158#ifdef BUILD_FEATURES
159const char *build_features = BUILD_FEATURES;
160#else
161const char *build_features = "";
162#endif
163
Willy Tarreau477ecd82010-01-03 21:12:30 +0100164/* list of config files */
165static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166int pid; /* current process id */
167
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100168volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100169volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100170
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171/* global options */
172struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100173 .hard_stop_after = TICK_ETERNITY,
Remi Tricot-Le Bretonb5d968d2022-04-08 18:04:18 +0200174 .close_spread_time = TICK_ETERNITY,
175 .close_spread_end = TICK_ETERNITY,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100176 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100177 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200178 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200179 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
Willy Tarreau197715a2022-04-25 19:29:10 +0200180 .maxzlibmem = DEFAULT_MAXZLIBMEM * 1024U * 1024U,
William Lallemandd85f9172012-11-09 17:05:39 +0100181 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100182 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200183 .unix_bind = {
184 .ux = {
185 .uid = -1,
186 .gid = -1,
187 .mode = 0,
188 }
189 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200190 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100191 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100192 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100193 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100194 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200195 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200196 .pool_low_ratio = 20,
197 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200198 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200199#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100200 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200201#endif
William Lallemandf3747832012-11-09 12:33:10 +0100202 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100203#ifdef DEFAULT_IDLE_TIMER
204 .idle_timer = DEFAULT_IDLE_TIMER,
205#else
206 .idle_timer = 1000, /* 1 second */
207#endif
Amaury Denoyelle97e84c62022-04-19 18:26:55 +0200208#ifdef USE_QUIC
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200209 .quic_backend_max_idle_timeout = QUIC_TP_DFLT_BACK_MAX_IDLE_TIMEOUT,
210 .quic_frontend_max_idle_timeout = QUIC_TP_DFLT_FRONT_MAX_IDLE_TIMEOUT,
211 .quic_frontend_max_streams_bidi = QUIC_TP_DFLT_FRONT_MAX_STREAMS_BIDI,
Frédéric Lécaille92862102022-05-20 16:29:10 +0200212 .quic_retry_threshold = QUIC_DFLT_RETRY_THRESHOLD,
Amaury Denoyelle97e84c62022-04-19 18:26:55 +0200213 .quic_streams_buf = 30,
214#endif /* USE_QUIC */
Willy Tarreau27a674e2009-08-17 07:23:33 +0200215 },
Emeric Brun76d88952012-10-05 15:47:31 +0200216#ifdef USE_OPENSSL
217#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200218 .maxsslconn = DEFAULT_MAXSSLCONN,
219#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200220#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 /* others NULL OK */
222};
223
224/*********************************************************************/
225
226int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100227int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200228int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100229int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100230int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100231int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreau392524d2022-02-17 18:10:36 +0100232int arg_mode = 0; /* MODE_DEBUG etc as passed on command line ... */
233char *change_dir = NULL; /* set when -C is passed */
234char *check_condition = NULL; /* check condition passed to -cc */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500236/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 * or kill. We will send them a signal every 10 ms until we can bind to all
238 * our ports. With 200 retries, that's about 2 seconds.
239 */
240#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241static int *oldpids = NULL;
242static int oldpids_sig; /* use USR1 or TERM */
243
Olivier Houchardf73629d2017-04-05 22:33:04 +0200244/* Path to the unix socket we use to retrieve listener sockets from the old process */
245static const char *old_unixsocket;
246
William Lallemandcb11fd22017-06-01 17:38:52 +0200247int atexit_flag = 0;
248
Willy Tarreaubb545b42010-08-25 12:58:59 +0200249int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250const int zero = 0;
251const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200252const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200253
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100254char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200255char *localpeer = NULL;
Willy Tarreau76871a42022-03-08 16:01:40 +0100256static char *kwd_dump = NULL; // list of keyword dumps to produce
Willy Tarreaubaaee002006-06-26 02:48:02 +0200257
William Lallemand00417412020-06-05 14:08:41 +0200258static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200259
William Lallemandbc193052018-09-11 10:06:26 +0200260struct list proc_list = LIST_HEAD_INIT(proc_list);
261
262int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100263unsigned int rlim_fd_cur_at_boot = 0;
264unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200265
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100266/* per-boot randomness */
267unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
268
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200269/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200270static void *run_thread_poll_loop(void *data);
271
Willy Tarreauff055502014-04-28 22:27:06 +0200272/* bitfield of a few warnings to emit just once (WARN_*) */
273unsigned int warned = 0;
274
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200275/* set if experimental features have been used for the current process */
Willy Tarreauedd42682022-02-25 10:10:00 +0100276unsigned int tainted = 0;
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200277
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200278unsigned int experimental_directives_allowed = 0;
279
280int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
281 char **errmsg)
282{
283 if (kw->flags & KWF_EXPERIMENTAL) {
284 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200285 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 +0200286 file, linenum, kw->kw);
287 return 1;
288 }
289 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
290 }
291
292 return 0;
293}
294
William Lallemande7361152018-10-26 14:47:36 +0200295/* master CLI configuration (-S flag) */
296struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100297
298/* These are strings to be reported in the output of "haproxy -vv". They may
299 * either be constants (in which case must_free must be zero) or dynamically
300 * allocated strings to pass to free() on exit, and in this case must_free
301 * must be non-zero.
302 */
303struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
304struct build_opts_str {
305 struct list list;
306 const char *str;
307 int must_free;
308};
309
Willy Tarreaubaaee002006-06-26 02:48:02 +0200310/*********************************************************************/
311/* general purpose functions ***************************************/
312/*********************************************************************/
313
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100314/* used to register some build option strings at boot. Set must_free to
315 * non-zero if the string must be freed upon exit.
316 */
317void hap_register_build_opts(const char *str, int must_free)
318{
319 struct build_opts_str *b;
320
321 b = calloc(1, sizeof(*b));
322 if (!b) {
323 fprintf(stderr, "out of memory\n");
324 exit(1);
325 }
326 b->str = str;
327 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200328 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100329}
330
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200331#define VERSION_MAX_ELTS 7
332
333/* This function splits an haproxy version string into an array of integers.
334 * The syntax of the supported version string is the following:
335 *
336 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
337 *
338 * This validates for example:
339 * 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
340 * 2.4-dev18-f6818d-20
341 *
342 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
343 * one fixed place in the array. The tags take a numeric value called <e> which
344 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
345 * considered as zero (henxe 1.5 and 1.5.0 are the same).
346 *
347 * The resulting values are:
348 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
349 * 1.2.1 1, 2, 1, 0, 3, 0, 0
350 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
351 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
352 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
353 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
354 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
355 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
356 *
357 * The function returns non-zero if the conversion succeeded, or zero if it
358 * failed.
359 */
360int split_version(const char *version, unsigned int *value)
361{
362 const char *p, *s;
363 char *error;
364 int nelts;
365
366 /* Initialize array with zeroes */
367 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
368 value[nelts] = 0;
369 value[4] = 3;
370
371 p = version;
372
373 /* If the version number is empty, return false */
374 if (*p == '\0')
375 return 0;
376
377 /* Convert first number <a> */
378 value[0] = strtol(p, &error, 10);
379 p = error + 1;
380 if (*error == '\0')
381 return 1;
382 if (*error == '-')
383 goto split_version_tag;
384 if (*error != '.')
385 return 0;
386
387 /* Convert first number <b> */
388 value[1] = strtol(p, &error, 10);
389 p = error + 1;
390 if (*error == '\0')
391 return 1;
392 if (*error == '-')
393 goto split_version_tag;
394 if (*error != '.')
395 return 0;
396
397 /* Convert first number <c> */
398 value[2] = strtol(p, &error, 10);
399 p = error + 1;
400 if (*error == '\0')
401 return 1;
402 if (*error == '-')
403 goto split_version_tag;
404 if (*error != '.')
405 return 0;
406
407 /* Convert first number <d> */
408 value[3] = strtol(p, &error, 10);
409 p = error + 1;
410 if (*error == '\0')
411 return 1;
412 if (*error != '-')
413 return 0;
414
415 split_version_tag:
416 /* Check for commit number */
417 if (*p >= '0' && *p <= '9')
418 goto split_version_commit;
419
420 /* Read tag */
421 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
422 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
423 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
424 else
425 goto split_version_commit;
426
427 /* Convert tag number */
428 value[5] = strtol(p, &error, 10);
429 p = error + 1;
430 if (*error == '\0')
431 return 1;
432 if (*error != '-')
433 return 0;
434
435 split_version_commit:
436 /* Search the last "-" */
437 s = strrchr(p, '-');
438 if (s) {
439 s++;
440 if (*s == '\0')
441 return 0;
442 value[6] = strtol(s, &error, 10);
443 if (*error != '\0')
444 value[6] = 0;
445 return 1;
446 }
447
448 /* convert the version */
449 value[6] = strtol(p, &error, 10);
450 if (*error != '\0')
451 value[6] = 0;
452
453 return 1;
454}
455
456/* This function compares the current haproxy version with an arbitrary version
457 * string. It returns:
458 * -1 : the version in argument is older than the current haproxy version
459 * 0 : the version in argument is the same as the current haproxy version
460 * 1 : the version in argument is newer than the current haproxy version
461 *
462 * Or some errors:
463 * -2 : the current haproxy version is not parsable
464 * -3 : the version in argument is not parsable
465 */
466int compare_current_version(const char *version)
467{
468 unsigned int loc[VERSION_MAX_ELTS];
469 unsigned int mod[VERSION_MAX_ELTS];
470 int i;
471
472 /* split versions */
473 if (!split_version(haproxy_version, loc))
474 return -2;
475 if (!split_version(version, mod))
476 return -3;
477
478 /* compare versions */
479 for (i = 0; i < VERSION_MAX_ELTS; i++) {
480 if (mod[i] < loc[i])
481 return -1;
482 else if (mod[i] > loc[i])
483 return 1;
484 }
485 return 0;
486}
487
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100488static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200489{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200490 struct utsname utsname;
491
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200492 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100493 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100494
495 if (strlen(PRODUCT_URL_BUGS) > 0) {
496 char base_version[20];
497 int dots = 0;
498 char *del;
499
500 /* only retrieve the base version without distro-specific extensions */
501 for (del = haproxy_version; *del; del++) {
502 if (*del == '.')
503 dots++;
504 else if (*del < '0' || *del > '9')
505 break;
506 }
507
508 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
509 if (dots < 2)
510 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
511 else
512 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
513 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200514
515 if (uname(&utsname) == 0) {
516 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200518}
519
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100520static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100521{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100522 struct build_opts_str *item;
523
Willy Tarreau7b066db2007-12-02 11:28:59 +0100524 printf("Build options :"
525#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100526 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100527#endif
528#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100529 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100530#endif
531#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100532 "\n CC = " BUILD_CC
533#endif
534#ifdef BUILD_CFLAGS
535 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100536#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100537#ifdef BUILD_OPTIONS
538 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100539#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100540#ifdef BUILD_DEBUG
541 "\n DEBUG = " BUILD_DEBUG
542#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100543#ifdef BUILD_FEATURES
544 "\n\nFeature list : " BUILD_FEATURES
545#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200546 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100547 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200548 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100549 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200550
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100551 list_for_each_entry(item, &build_opts_list, list) {
552 puts(item->str);
553 }
554
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100555 putchar('\n');
556
Willy Tarreaube5b6852009-10-03 18:57:08 +0200557 list_pollers(stdout);
558 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200559 list_mux_proto(stdout);
560 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100561 list_services(stdout);
562 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100563 list_filters(stdout);
564 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100565}
566
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567/*
568 * This function prints the command line usage and exits
569 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100570static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200571{
572 display_version();
573 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200574 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200576 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100577 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200578 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreauf4b79c42022-02-23 15:20:53 +0100579 " -dM[<byte>,help,...] debug memory (default: poison with <byte>/0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200581 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200582 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100583#if defined(USE_SYSTEMD)
584 " -Ws master-worker mode with systemd notify support.\n"
585#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200587 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200588 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100589 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 " -m limits the usable amount of memory (in MB)\n"
591 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200592 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200593 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200594#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 " -de disables epoll() usage even when available\n"
596#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200597#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200598 " -dk disables kqueue() usage even when available\n"
599#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200600#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000601 " -dv disables event ports usage even when available\n"
602#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200603#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 " -dp disables poll() usage even when available\n"
605#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200606#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100607 " -dS disables splice usage (broken on old kernels)\n"
608#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200609#if defined(USE_GETADDRINFO)
610 " -dG disables getaddrinfo() usage\n"
611#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000612#if defined(SO_REUSEPORT)
613 " -dR disables SO_REUSEPORT usage\n"
614#endif
Willy Tarreau654726d2021-12-28 15:43:11 +0100615#if defined(HA_HAVE_DUMP_LIBS)
616 " -dL dumps loaded object files after config checks\n"
617#endif
Willy Tarreau76871a42022-03-08 16:01:40 +0100618 " -dK{class[,...]} dump registered keywords (use 'help' for list)\n"
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100619 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100620 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200621 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200622 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200623 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200624 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200625 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100627 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 exit(1);
629}
630
631
632
633/*********************************************************************/
634/* more specific functions ***************************************/
635/*********************************************************************/
636
William Lallemand73b85e72017-06-01 17:38:51 +0200637/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
638 * pids the signal was correctly delivered to.
639 */
William Lallemande25473c2019-04-01 11:29:56 +0200640int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200641{
642 int p;
643 int ret = 0;
644 for (p = 0; p < nb_oldpids; p++)
645 if (kill(oldpids[p], sig) == 0)
646 ret++;
647 return ret;
648}
649
William Lallemand75ea0a02017-11-15 19:02:58 +0100650/*
William Lallemand73b85e72017-06-01 17:38:51 +0200651 * remove a pid forom the olpid array and decrease nb_oldpids
652 * return 1 pid was found otherwise return 0
653 */
654
655int delete_oldpid(int pid)
656{
657 int i;
658
659 for (i = 0; i < nb_oldpids; i++) {
660 if (oldpids[i] == pid) {
661 oldpids[i] = oldpids[nb_oldpids - 1];
662 oldpids[nb_oldpids - 1] = 0;
663 nb_oldpids--;
664 return 1;
665 }
666 }
667 return 0;
668}
669
William Lallemand85b0bd92017-06-01 17:38:53 +0200670
William Lallemand73b85e72017-06-01 17:38:51 +0200671/*
672 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800673 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200674 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100675static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200676{
William Lallemand00417412020-06-05 14:08:41 +0200677 char **next_argv = NULL;
678 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200679 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200680 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200681 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100682 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100683 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200684
685 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100686#if defined(USE_SYSTEMD)
687 if (global.tune.options & GTUNE_USE_SYSTEMD)
688 sd_notify(0, "RELOADING=1");
689#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200690 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
691
William Lallemand55a921c2022-01-28 21:17:30 +0100692 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200693 mworker_proc_list_to_env(); /* put the children description in the env */
694
William Lallemandc4810b82021-11-18 10:51:30 +0100695 /* ensure that we close correctly every listeners before reexecuting */
696 mworker_cleanlisteners();
697
William Lallemand7c756a82018-11-26 11:53:40 +0100698 /* during the reload we must ensure that every FDs that can't be
699 * reuse (ie those that are not referenced in the proc_list)
700 * are closed or they will leak. */
701
702 /* close the listeners FD */
703 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200704
William Lallemand67e371e2021-11-25 10:03:44 +0100705 if (fdtab)
706 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100707
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500708#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200709 /* close random device FDs */
710 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100711#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100712
Willy Tarreau8dca1952019-03-01 10:21:55 +0100713 /* restore the initial FD limits */
714 limit.rlim_cur = rlim_fd_cur_at_boot;
715 limit.rlim_max = rlim_fd_max_at_boot;
716 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
717 getrlimit(RLIMIT_NOFILE, &limit);
718 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
719 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
720 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
721 }
722
William Lallemand73b85e72017-06-01 17:38:51 +0200723 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200724 while (old_argv[old_argc])
725 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200726
William Lallemand85b0bd92017-06-01 17:38:53 +0200727 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200728 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200729 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200730 if (next_argv == NULL)
731 goto alloc_error;
732
William Lallemand00417412020-06-05 14:08:41 +0200733 /* copy the program name */
734 next_argv[next_argc++] = old_argv[0];
735
736 /* insert the new options just after argv[0] in case we have a -- */
737
William Lallemandbefab9e2021-11-25 00:49:19 +0100738 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
739 /* add -sf <PID>* to argv */
740 if (mworker_child_nb() > 0) {
741 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200742
William Lallemandbefab9e2021-11-25 00:49:19 +0100743 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200744
William Lallemandbefab9e2021-11-25 00:49:19 +0100745 list_for_each_entry(child, &proc_list, list) {
746 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
747 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100748
William Lallemandbefab9e2021-11-25 00:49:19 +0100749 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
750 continue;
751 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
752 goto alloc_error;
753 msg = NULL;
754 }
William Lallemand73b85e72017-06-01 17:38:51 +0200755 }
William Lallemand2be557f2021-11-24 18:45:37 +0100756
757 if (current_child) {
758 /* add the -x option with the socketpair of the current worker */
759 next_argv[next_argc++] = "-x";
760 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
761 goto alloc_error;
762 msg = NULL;
763 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200764 }
765
William Lallemand00417412020-06-05 14:08:41 +0200766 /* copy the previous options */
767 for (i = 1; i < old_argc; i++)
768 next_argv[next_argc++] = old_argv[i];
769
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200770 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100771 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100772 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100773 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100774 return;
775
William Lallemand73b85e72017-06-01 17:38:51 +0200776alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100777 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800778 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200779 return;
780}
781
William Lallemandfab0fdc2021-11-09 18:01:22 +0100782/* reexec haproxy in waitmode */
783static void mworker_reexec_waitmode()
784{
785 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
786 mworker_reexec();
787}
788
789/* reload haproxy and emit a warning */
790void mworker_reload()
791{
William Lallemandad221f42021-11-09 18:43:59 +0100792 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100793 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100794
William Lallemand836bda22021-11-09 18:16:47 +0100795 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100796
William Lallemandefd95472021-11-26 14:43:57 +0100797 /* close the poller FD and the thread waker pipe FD */
798 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
799 ptdf->fct();
800
William Lallemandad221f42021-11-09 18:43:59 +0100801 /* increment the number of reloads */
802 list_for_each_entry(child, &proc_list, list) {
803 child->reloads++;
804 }
805
William Lallemandfab0fdc2021-11-09 18:01:22 +0100806 mworker_reexec();
807}
808
William Lallemandb3f2be32018-09-11 10:06:18 +0200809static void mworker_loop()
810{
811
812#if defined(USE_SYSTEMD)
813 if (global.tune.options & GTUNE_USE_SYSTEMD)
814 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
815#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200816 /* Busy polling makes no sense in the master :-) */
817 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200818
William Lallemandbc193052018-09-11 10:06:26 +0200819
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100820 signal_unregister(SIGTTIN);
821 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100822 signal_unregister(SIGUSR1);
823 signal_unregister(SIGHUP);
824 signal_unregister(SIGQUIT);
825
William Lallemandb3f2be32018-09-11 10:06:18 +0200826 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
827 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100828 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
829 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200830 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
831 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
832 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
833 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
834
835 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100836 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200837
William Lallemandbc193052018-09-11 10:06:26 +0200838 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
839 some SIGCHLD were lost */
840
William Lallemandb3f2be32018-09-11 10:06:18 +0200841 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200842
William Lallemand2672eb92018-12-14 15:52:39 +0100843#ifdef USE_THREAD
844 tid_bit = 1;
845 all_threads_mask = 1;
846#endif
847
William Lallemandb3f2be32018-09-11 10:06:18 +0200848 jobs++; /* this is the "master" job, we want to take care of the
849 signals even if there is no listener so the poll loop don't
850 leave */
851
852 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200853 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200854}
William Lallemandcb11fd22017-06-01 17:38:52 +0200855
856/*
857 * Reexec the process in failure mode, instead of exiting
858 */
859void reexec_on_failure()
860{
William Lallemand68836742021-11-10 10:49:06 +0100861 struct mworker_proc *child;
862
William Lallemandcb11fd22017-06-01 17:38:52 +0200863 if (!atexit_flag)
864 return;
William Lallemand68836742021-11-10 10:49:06 +0100865
866 /* get the info of the children in the env */
867 if (mworker_env_to_proc_list() < 0) {
868 exit(EXIT_FAILURE);
869 }
870
871 /* increment the number of failed reloads */
872 list_for_each_entry(child, &proc_list, list) {
873 child->failedreloads++;
874 }
875
Willy Tarreaue08acae2022-01-28 18:40:06 +0100876 /* do not keep unused FDs retrieved from the previous process */
877 sock_drop_unused_old_sockets();
878
William Lallemandfab0fdc2021-11-09 18:01:22 +0100879 usermsgs_clr(NULL);
William Lallemand836bda22021-11-09 18:16:47 +0100880 ha_warning("Loading failure!\n");
William Lallemandfab0fdc2021-11-09 18:01:22 +0100881 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200882}
William Lallemand73b85e72017-06-01 17:38:51 +0200883
884
885/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200886 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
887 * a signal zero to all subscribers. This means that it's as easy as
888 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100890static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891{
892 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200893 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100894 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895}
896
897/*
898 * upon SIGTTOU, we pause everything
899 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100900static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901{
Willy Tarreau775e0012020-09-24 16:36:26 +0200902 if (protocol_pause_all() & ERR_FATAL) {
903 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200904 ha_warning("%s", msg);
905 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200906 soft_stop();
907 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100908 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200909}
910
911/*
912 * upon SIGTTIN, let's have a soft stop.
913 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100914static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915{
Willy Tarreau775e0012020-09-24 16:36:26 +0200916 if (protocol_resume_all() & ERR_FATAL) {
917 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 +0200918 ha_warning("%s", msg);
919 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921}
922
923/*
924 * this function dumps every server's state when the process receives SIGHUP.
925 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100926static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100928 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200929
Christopher Faulet767a84b2017-11-24 16:50:31 +0100930 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 while (p) {
932 struct server *s = p->srv;
933
934 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
935 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100936 chunk_printf(&trash,
937 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
938 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200939 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200940 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200941 ha_warning("%s\n", trash.area);
942 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200943 s = s->next;
944 }
945
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200946 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
947 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100948 chunk_printf(&trash,
949 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
950 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200951 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 +0200952 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100953 chunk_printf(&trash,
954 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
955 p->id,
956 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200957 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 +0200958 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100959 chunk_printf(&trash,
960 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
961 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
962 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200963 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 +0200964 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200965 ha_warning("%s\n", trash.area);
966 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967
968 p = p->next;
969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970}
971
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100972static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200974 /* dump memory usage then free everything possible */
975 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100976 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977}
978
William Lallemande1340412017-12-28 16:09:36 +0100979/*
980 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
981 * If <fd> < 0, it opens /dev/null and use it to dup
982 *
983 * In the case of chrooting, you have to open /dev/null before the chroot, and
984 * pass the <fd> to this function
985 */
986static void stdio_quiet(int fd)
987{
988 if (fd < 0)
989 fd = open("/dev/null", O_RDWR, 0);
990
991 if (fd > -1) {
992 fclose(stdin);
993 fclose(stdout);
994 fclose(stderr);
995
996 dup2(fd, 0);
997 dup2(fd, 1);
998 dup2(fd, 2);
999 if (fd > 2)
1000 close(fd);
1001 return;
1002 }
1003
1004 ha_alert("Cannot open /dev/null\n");
1005 exit(EXIT_FAILURE);
1006}
1007
1008
Joseph Herlant03420902018-11-15 10:41:50 -08001009/* This function checks if cfg_cfgfiles contains directories.
1010 * If it finds one, it adds all the files (and only files) it contains
1011 * in cfg_cfgfiles in place of the directory (and removes the directory).
1012 * It adds the files in lexical order.
1013 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001014 * It doesn't add files with name starting with '.'
1015 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001016static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001017{
1018 struct wordlist *wl, *wlb;
1019 char *err = NULL;
1020
1021 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1022 struct stat file_stat;
1023 struct dirent **dir_entries = NULL;
1024 int dir_entries_nb;
1025 int dir_entries_it;
1026
1027 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001028 ha_alert("Cannot open configuration file/directory %s : %s\n",
1029 wl->s,
1030 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001031 exit(1);
1032 }
1033
1034 if (!S_ISDIR(file_stat.st_mode))
1035 continue;
1036
1037 /* from this point wl->s is a directory */
1038
1039 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1040 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001041 ha_alert("Cannot open configuration directory %s : %s\n",
1042 wl->s,
1043 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001044 exit(1);
1045 }
1046
1047 /* for each element in the directory wl->s */
1048 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1049 struct dirent *dir_entry = dir_entries[dir_entries_it];
1050 char *filename = NULL;
1051 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1052
1053 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001054 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001055 */
1056 if (dir_entry->d_name[0] == '.' ||
1057 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1058 goto next_dir_entry;
1059
1060 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001061 ha_alert("Cannot load configuration files %s : out of memory.\n",
1062 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001063 exit(1);
1064 }
1065
1066 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001067 ha_alert("Cannot open configuration file %s : %s\n",
1068 wl->s,
1069 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001070 exit(1);
1071 }
1072
1073 /* don't add anything else than regular file in cfg_cfgfiles
1074 * this way we avoid loops
1075 */
1076 if (!S_ISREG(file_stat.st_mode))
1077 goto next_dir_entry;
1078
1079 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001080 ha_alert("Cannot load configuration files %s : %s\n",
1081 filename,
1082 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001083 exit(1);
1084 }
1085
1086next_dir_entry:
1087 free(filename);
1088 free(dir_entry);
1089 }
1090
1091 free(dir_entries);
1092
1093 /* remove the current directory (wl) from cfg_cfgfiles */
1094 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001095 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001096 free(wl);
1097 }
1098
1099 free(err);
1100}
1101
Willy Tarreaubaaee002006-06-26 02:48:02 +02001102/*
William Lallemand73b85e72017-06-01 17:38:51 +02001103 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001104 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001105 * Return an allocated copy of argv
1106 */
1107
1108static char **copy_argv(int argc, char **argv)
1109{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001110 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001111
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001112 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001113 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001114 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001115 return NULL;
1116 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001117 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001118
William Lallemanddf6c5a82020-06-04 17:40:23 +02001119 /* first copy argv[0] */
1120 *newargv++ = *argv++;
1121 argc--;
1122
1123 while (argc > 0) {
1124 if (**argv != '-') {
1125 /* non options are copied but will fail in the argument parser */
1126 *newargv++ = *argv++;
1127 argc--;
1128
1129 } else {
1130 char *flag;
1131
1132 flag = *argv + 1;
1133
1134 if (flag[0] == '-' && flag[1] == 0) {
1135 /* "--\0" copy every arguments till the end of argv */
1136 *newargv++ = *argv++;
1137 argc--;
1138
1139 while (argc > 0) {
1140 *newargv++ = *argv++;
1141 argc--;
1142 }
1143 } else {
1144 switch (*flag) {
1145 case 's':
1146 /* -sf / -st and their parameters are ignored */
1147 if (flag[1] == 'f' || flag[1] == 't') {
1148 argc--;
1149 argv++;
1150 /* The list can't contain a negative value since the only
1151 way to know the end of this list is by looking for the
1152 next option or the end of the options */
1153 while (argc > 0 && argv[0][0] != '-') {
1154 argc--;
1155 argv++;
1156 }
William Lallemand398da622020-09-02 16:12:23 +02001157 } else {
1158 argc--;
1159 argv++;
1160
William Lallemanddf6c5a82020-06-04 17:40:23 +02001161 }
1162 break;
1163
1164 case 'x':
1165 /* this option and its parameter are ignored */
1166 argc--;
1167 argv++;
1168 if (argc > 0) {
1169 argc--;
1170 argv++;
1171 }
1172 break;
1173
1174 case 'C':
1175 case 'n':
1176 case 'm':
1177 case 'N':
1178 case 'L':
1179 case 'f':
1180 case 'p':
1181 case 'S':
1182 /* these options have only 1 parameter which must be copied and can start with a '-' */
1183 *newargv++ = *argv++;
1184 argc--;
1185 if (argc == 0)
1186 goto error;
1187 *newargv++ = *argv++;
1188 argc--;
1189 break;
1190 default:
1191 /* for other options just copy them without parameters, this is also done
1192 * for options like "--foo", but this will fail in the argument parser.
1193 * */
1194 *newargv++ = *argv++;
1195 argc--;
1196 break;
1197 }
William Lallemand73b85e72017-06-01 17:38:51 +02001198 }
1199 }
William Lallemand73b85e72017-06-01 17:38:51 +02001200 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001201
William Lallemanddf6c5a82020-06-04 17:40:23 +02001202 return retargv;
1203
1204error:
1205 free(retargv);
1206 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001207}
1208
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001209
1210/* Performs basic random seed initialization. The main issue with this is that
1211 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1212 * which means that there will only be 4 billion possible random sequences once
1213 * srandom() is called, regardless of the internal state. Not calling it is
1214 * even worse as we'll always produce the same randoms sequences. What we do
1215 * here is to create an initial sequence from various entropy sources, hash it
1216 * using SHA1 and keep the resulting 160 bits available globally.
1217 *
1218 * We initialize the current process with the first 32 bits before starting the
1219 * polling loop, where all this will be changed to have process specific and
1220 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001221 *
1222 * Before starting threads, it's still possible to call random() as srandom()
1223 * is initialized from this, but after threads and/or processes are started,
1224 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001225 */
1226static void ha_random_boot(char *const *argv)
1227{
1228 unsigned char message[256];
1229 unsigned char *m = message;
1230 struct timeval tv;
1231 blk_SHA_CTX ctx;
1232 unsigned long l;
1233 int fd;
1234 int i;
1235
1236 /* start with current time as pseudo-random seed */
1237 gettimeofday(&tv, NULL);
1238 write_u32(m, tv.tv_sec); m += 4;
1239 write_u32(m, tv.tv_usec); m += 4;
1240
1241 /* PID and PPID add some OS-based randomness */
1242 write_u16(m, getpid()); m += 2;
1243 write_u16(m, getppid()); m += 2;
1244
1245 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1246 fd = open("/dev/urandom", O_RDONLY);
1247 if (fd >= 0) {
1248 i = read(fd, m, 20);
1249 if (i > 0)
1250 m += i;
1251 close(fd);
1252 }
1253
1254 /* take up to 160 bits bytes from openssl (non-blocking) */
1255#ifdef USE_OPENSSL
1256 if (RAND_bytes(m, 20) == 1)
1257 m += 20;
1258#endif
1259
1260 /* take 160 bits from existing random in case it was already initialized */
1261 for (i = 0; i < 5; i++) {
1262 write_u32(m, random());
1263 m += 4;
1264 }
1265
1266 /* stack address (benefit form operating system's ASLR) */
1267 l = (unsigned long)&m;
1268 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1269
1270 /* argv address (benefit form operating system's ASLR) */
1271 l = (unsigned long)&argv;
1272 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1273
1274 /* use tv_usec again after all the operations above */
1275 gettimeofday(&tv, NULL);
1276 write_u32(m, tv.tv_usec); m += 4;
1277
1278 /*
1279 * At this point, ~84-92 bytes have been used
1280 */
1281
1282 /* finish with the hostname */
1283 strncpy((char *)m, hostname, message + sizeof(message) - m);
1284 m += strlen(hostname);
1285
1286 /* total message length */
1287 l = m - message;
1288
1289 memset(&ctx, 0, sizeof(ctx));
1290 blk_SHA1_Init(&ctx);
1291 blk_SHA1_Update(&ctx, message, l);
1292 blk_SHA1_Final(boot_seed, &ctx);
1293
1294 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001295 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001296}
1297
Willy Tarreau5a023f02019-03-01 14:19:31 +01001298/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1299 * setting, and returns it. It may return -1 meaning "unlimited" if some
1300 * unlimited proxies have been found and the global.maxconn value is not yet
1301 * set. It may also return a value greater than maxconn if it's not yet set.
1302 * Note that a value of zero means there is no need for pipes. -1 is never
1303 * returned if global.maxconn is valid.
1304 */
1305static int compute_ideal_maxpipes()
1306{
1307 struct proxy *cur;
1308 int nbfe = 0, nbbe = 0;
1309 int unlimited = 0;
1310 int pipes;
1311 int max;
1312
1313 for (cur = proxies_list; cur; cur = cur->next) {
1314 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1315 if (cur->cap & PR_CAP_FE) {
1316 max = cur->maxconn;
1317 nbfe += max;
1318 if (!max) {
1319 unlimited = 1;
1320 break;
1321 }
1322 }
1323 if (cur->cap & PR_CAP_BE) {
1324 max = cur->fullconn ? cur->fullconn : global.maxconn;
1325 nbbe += max;
1326 if (!max) {
1327 unlimited = 1;
1328 break;
1329 }
1330 }
1331 }
1332 }
1333
1334 pipes = MAX(nbfe, nbbe);
1335 if (global.maxconn) {
1336 if (pipes > global.maxconn || unlimited)
1337 pipes = global.maxconn;
1338 } else if (unlimited) {
1339 pipes = -1;
1340 }
1341
1342 return pipes >= 4 ? pipes / 4 : pipes;
1343}
1344
Willy Tarreauac350932019-03-01 15:43:14 +01001345/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1346 * rlimits and computes an ideal maxconn. It's meant to be called only when
1347 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001348 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1349 * default 100) is returned as it is expected that it will even run on tight
1350 * environments, and will maintain compatibility with previous packages that
1351 * used to rely on this value as the default one. The system will emit a
1352 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001353 */
1354static int compute_ideal_maxconn()
1355{
1356 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1357 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1358 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001359 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001360 int maxconn;
1361
1362 /* we have to take into account these elements :
1363 * - number of engine_fds, which inflates the number of FD needed per
1364 * connection by this number.
1365 * - number of pipes per connection on average : for the unlimited
1366 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1367 * fixed value of 2*pipes.
1368 * - two FDs per connection
1369 */
1370
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001371 if (global.fd_hard_limit && remain > global.fd_hard_limit)
1372 remain = global.fd_hard_limit;
1373
Willy Tarreauac350932019-03-01 15:43:14 +01001374 /* subtract listeners and checks */
1375 remain -= global.maxsock;
1376
Willy Tarreau3f200852019-03-14 19:13:17 +01001377 /* one epoll_fd/kqueue_fd per thread */
1378 remain -= global.nbthread;
1379
1380 /* one wake-up pipe (2 fd) per thread */
1381 remain -= 2 * global.nbthread;
1382
Willy Tarreauac350932019-03-01 15:43:14 +01001383 /* Fixed pipes values : we only subtract them if they're not larger
1384 * than the remaining FDs because pipes are optional.
1385 */
1386 if (pipes >= 0 && pipes * 2 < remain)
1387 remain -= pipes * 2;
1388
1389 if (pipes < 0) {
1390 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1391 * = maxconn * (2 + 0.5 + engine_fds)
1392 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1393 */
1394 maxconn = 2 * remain / (5 + 2 * engine_fds);
1395 } else {
1396 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1397 * = maxconn * (2 + engine_fds)
1398 */
1399 maxconn = remain / (2 + engine_fds);
1400 }
1401
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001402 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001403}
1404
Willy Tarreaua409f302020-03-10 17:08:53 +01001405/* computes the estimated maxsock value for the given maxconn based on the
1406 * possibly set global.maxpipes and existing partial global.maxsock. It may
1407 * temporarily change global.maxconn for the time needed to propagate the
1408 * computations, and will reset it.
1409 */
1410static int compute_ideal_maxsock(int maxconn)
1411{
1412 int maxpipes = global.maxpipes;
1413 int maxsock = global.maxsock;
1414
1415
1416 if (!maxpipes) {
1417 int old_maxconn = global.maxconn;
1418
1419 global.maxconn = maxconn;
1420 maxpipes = compute_ideal_maxpipes();
1421 global.maxconn = old_maxconn;
1422 }
1423
1424 maxsock += maxconn * 2; /* each connection needs two sockets */
1425 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1426 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1427 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1428
1429 /* compute fd used by async engines */
1430 if (global.ssl_used_async_engines) {
1431 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1432
1433 maxsock += maxconn * sides * global.ssl_used_async_engines;
1434 }
1435 return maxsock;
1436}
1437
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001438/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001439 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1440 * value is accepted, non-zero otherwise. This is used to determine if an
1441 * automatic limit may be applied or not. When it is not, the caller knows that
1442 * the highest we can do is the rlim_max at boot. In case of error, we return
1443 * that the setting is possible, so that we defer the error processing to the
1444 * final stage in charge of enforcing this.
1445 */
1446static int check_if_maxsock_permitted(int maxsock)
1447{
1448 struct rlimit orig_limit, test_limit;
1449 int ret;
1450
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001451 if (global.fd_hard_limit && maxsock > global.fd_hard_limit)
1452 return 0;
1453
Willy Tarreau304e17e2020-03-10 17:54:54 +01001454 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1455 return 1;
1456
1457 /* don't go further if we can't even set to what we have */
1458 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1459 return 1;
1460
1461 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1462 test_limit.rlim_cur = test_limit.rlim_max;
1463 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1464
1465 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1466 return 1;
1467
1468 return ret == 0;
1469}
1470
Willy Tarreau34527d52022-02-17 17:45:58 +01001471/* This performs th every basic early initialization at the end of the PREPARE
1472 * init stage. It may only assume that list heads are initialized, but not that
1473 * anything else is correct. It will initialize a number of variables that
1474 * depend on command line and will pre-parse the command line. If it fails, it
1475 * directly exits.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001476 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001477static void init_early(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478{
Kevinm48936af2010-12-22 16:08:21 +00001479 char *progname;
Willy Tarreau34527d52022-02-17 17:45:58 +01001480 char *tmp;
1481 int len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001482
Willy Tarreau34527d52022-02-17 17:45:58 +01001483 /* First, let's initialize most global variables */
1484 totalconn = actconn = listeners = stopping = 0;
1485 killed = pid = 0;
1486
1487 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
1488 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Christopher Faulete3a5e352017-10-24 13:53:54 +02001489 global.mode = MODE_STARTING;
William Lallemand73b85e72017-06-01 17:38:51 +02001490
Willy Tarreau34527d52022-02-17 17:45:58 +01001491 /* if we were in mworker mode, we should restart in mworker mode */
1492 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1493 global.mode |= MODE_MWORKER;
David du Colombier7af46052012-05-16 14:16:48 +02001494
Willy Tarreau34527d52022-02-17 17:45:58 +01001495 /* initialize date, time, and pid */
1496 tzset();
1497 clock_init_process_date();
1498 start_date = now;
1499 pid = getpid();
1500
1501 /* Set local host name and adjust some environment variables.
1502 * NB: POSIX does not make it mandatory for gethostname() to
1503 * NULL-terminate the string in case of truncation, and at least
1504 * FreeBSD appears not to do it.
Emeric Brun2b920a12010-09-23 18:30:22 +02001505 */
1506 memset(hostname, 0, sizeof(hostname));
1507 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001508
Willy Tarreau34527d52022-02-17 17:45:58 +01001509 /* preset some environment variables */
1510 localpeer = strdup(hostname);
1511 if (!localpeer || setenv("HAPROXY_LOCALPEER", localpeer, 1) < 0) {
Dragan Dosen4f014152020-06-18 16:56:47 +02001512 ha_alert("Cannot allocate memory for local peer.\n");
1513 exit(EXIT_FAILURE);
1514 }
Emeric Brun2b920a12010-09-23 18:30:22 +02001515
Willy Tarreau34527d52022-02-17 17:45:58 +01001516 /* Some CPU affinity stuff may have to be initialized */
1517#ifdef USE_CPU_AFFINITY
1518 {
1519 int i;
1520 ha_cpuset_zero(&cpu_map.proc);
1521 ha_cpuset_zero(&cpu_map.proc_t1);
1522 for (i = 0; i < MAX_THREADS; ++i) {
1523 ha_cpuset_zero(&cpu_map.thread[i]);
1524 }
1525 }
1526#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001527
Willy Tarreau34527d52022-02-17 17:45:58 +01001528 /* extract the program name from argv[0], it will be used for the logs
1529 * and error messages.
1530 */
1531 progname = *argv;
1532 while ((tmp = strchr(progname, '/')) != NULL)
1533 progname = tmp + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001534
Willy Tarreau34527d52022-02-17 17:45:58 +01001535 len = strlen(progname);
1536 progname = strdup(progname);
1537 if (!progname) {
1538 ha_alert("Cannot allocate memory for log_tag.\n");
1539 exit(EXIT_FAILURE);
1540 }
Willy Tarreau84310e22014-02-14 11:59:04 +01001541
Willy Tarreau34527d52022-02-17 17:45:58 +01001542 chunk_initlen(&global.log_tag, progname, len, len);
1543}
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001544
Willy Tarreau392524d2022-02-17 18:10:36 +01001545/* handles program arguments. Very minimal parsing is performed, variables are
1546 * fed with some values, and lists are completed with other ones. In case of
1547 * error, it will exit.
Willy Tarreau34527d52022-02-17 17:45:58 +01001548 */
Willy Tarreau392524d2022-02-17 18:10:36 +01001549static void init_args(int argc, char **argv)
Willy Tarreau34527d52022-02-17 17:45:58 +01001550{
Willy Tarreau34527d52022-02-17 17:45:58 +01001551 char *progname = global.log_tag.area;
Willy Tarreau392524d2022-02-17 18:10:36 +01001552 char *err_msg = NULL;
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001553
Willy Tarreau34527d52022-02-17 17:45:58 +01001554 /* pre-fill in the global tuning options before we let the cmdline
1555 * change them.
1556 */
Willy Tarreau43b78992009-01-25 15:42:27 +01001557 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001558#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001559 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001561#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001562 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001564#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001565 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001566#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001567#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001568 global.tune.options |= GTUNE_USE_EVPORTS;
1569#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001570#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001571 global.tune.options |= GTUNE_USE_SPLICE;
1572#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001573#if defined(USE_GETADDRINFO)
1574 global.tune.options |= GTUNE_USE_GAI;
1575#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001576#if defined(SO_REUSEPORT)
1577 global.tune.options |= GTUNE_USE_REUSEPORT;
1578#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001579#ifdef USE_THREAD
1580 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1581#endif
William Dauchya5194602020-03-28 19:29:58 +01001582 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583
Willy Tarreau392524d2022-02-17 18:10:36 +01001584 /* keep a copy of original arguments for the master process */
1585 old_argv = copy_argv(argc, argv);
1586 if (!old_argv) {
1587 ha_alert("failed to copy argv.\n");
1588 exit(EXIT_FAILURE);
1589 }
1590
1591 /* skip program name and start */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 argc--; argv++;
1593 while (argc > 0) {
1594 char *flag;
1595
1596 if (**argv == '-') {
1597 flag = *argv+1;
1598
1599 /* 1 arg */
1600 if (*flag == 'v') {
1601 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001602 if (flag[1] == 'v') /* -vv */
1603 display_build_opts();
Tim Duesterhus77b3db02022-04-27 00:08:11 +02001604 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001606#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001608 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001610#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001612 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001614#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001615 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001616 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001617#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001618#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001619 else if (*flag == 'd' && flag[1] == 'v')
1620 global.tune.options &= ~GTUNE_USE_EVPORTS;
1621#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001622#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001623 else if (*flag == 'd' && flag[1] == 'S')
1624 global.tune.options &= ~GTUNE_USE_SPLICE;
1625#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001626#if defined(USE_GETADDRINFO)
1627 else if (*flag == 'd' && flag[1] == 'G')
1628 global.tune.options &= ~GTUNE_USE_GAI;
1629#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001630#if defined(SO_REUSEPORT)
1631 else if (*flag == 'd' && flag[1] == 'R')
1632 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1633#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001634 else if (*flag == 'd' && flag[1] == 'V')
1635 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636 else if (*flag == 'V')
1637 arg_mode |= MODE_VERBOSE;
1638 else if (*flag == 'd' && flag[1] == 'b')
1639 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001640 else if (*flag == 'd' && flag[1] == 'D')
1641 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001642 else if (*flag == 'd' && flag[1] == 'W')
1643 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreauef301b72022-02-23 14:15:18 +01001644 else if (*flag == 'd' && flag[1] == 'M') {
Willy Tarreau1408b1f2022-02-18 18:54:40 +01001645 int ret = pool_parse_debugging(flag + 2, &err_msg);
1646
1647 if (ret <= -1) {
1648 if (ret < -1)
1649 ha_alert("-dM: %s\n", err_msg);
1650 else
1651 printf("%s\n", err_msg);
1652 ha_free(&err_msg);
1653 exit(ret < -1 ? EXIT_FAILURE : 0);
1654 } else if (ret == 0) {
1655 ha_warning("-dM: %s\n", err_msg);
1656 ha_free(&err_msg);
1657 }
Willy Tarreauef301b72022-02-23 14:15:18 +01001658 }
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001659 else if (*flag == 'd' && flag[1] == 'r')
1660 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001661#if defined(HA_HAVE_DUMP_LIBS)
1662 else if (*flag == 'd' && flag[1] == 'L')
1663 arg_mode |= MODE_DUMP_LIBS;
1664#endif
Willy Tarreau76871a42022-03-08 16:01:40 +01001665 else if (*flag == 'd' && flag[1] == 'K') {
1666 arg_mode |= MODE_DUMP_KWD;
1667 kwd_dump = flag + 2;
1668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001669 else if (*flag == 'd')
1670 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001671 else if (*flag == 'c' && flag[1] == 'c') {
1672 arg_mode |= MODE_CHECK_CONDITION;
1673 argv++;
1674 argc--;
1675 check_condition = *argv;
1676 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001677 else if (*flag == 'c')
1678 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001679 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001680 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001681 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001682 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001683#if defined(USE_SYSTEMD)
1684 global.tune.options |= GTUNE_USE_SYSTEMD;
1685#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001686 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 +01001687 usage(progname);
1688#endif
1689 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001690 else if (*flag == 'W')
1691 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001692 else if (*flag == 'q')
1693 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001694 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001695 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001696 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001697 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001698 }
William Lallemand4fc09692017-06-19 16:37:19 +02001699 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001700 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001701 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001702
Olivier Houchardf73629d2017-04-05 22:33:04 +02001703 argv++;
1704 argc--;
1705 }
William Lallemande7361152018-10-26 14:47:36 +02001706 else if (*flag == 'S') {
1707 struct wordlist *c;
1708
William Lallemanda6b32492020-06-04 23:49:20 +02001709 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001710 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1711 usage(progname);
1712 }
1713 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1714 ha_alert("Cannot allocate memory\n");
1715 exit(EXIT_FAILURE);
1716 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001717 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001718
1719 argv++;
1720 argc--;
1721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1723 /* list of pids to finish ('f') or terminate ('t') */
1724
1725 if (flag[1] == 'f')
1726 oldpids_sig = SIGUSR1; /* finish then exit */
1727 else
1728 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001729 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001730 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001731 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1732 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001733 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001734 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001735 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001736 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001737 errno = 0;
1738 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1739 if (errno) {
1740 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1741 flag,
1742 *argv, strerror(errno));
1743 exit(1);
1744 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001745 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001746 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001747 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1748 flag, endptr);
1749 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001750 }
Chris Lane236062f2018-02-05 23:15:44 +00001751 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001752 if (oldpids[nb_oldpids] <= 0)
1753 usage(progname);
1754 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001755 }
1756 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001757 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1758 /* now that's a cfgfile list */
1759 argv++; argc--;
1760 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001761 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001762 ha_alert("Cannot load configuration file/directory %s : %s\n",
1763 *argv,
1764 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001765 exit(1);
1766 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001767 argv++; argc--;
1768 }
1769 break;
1770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771 else { /* >=2 args */
1772 argv++; argc--;
1773 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001774 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775
1776 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001777 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001779 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001780 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001781 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001782 free(localpeer);
1783 if ((localpeer = strdup(*argv)) == NULL) {
1784 ha_alert("Cannot allocate memory for local peer.\n");
1785 exit(EXIT_FAILURE);
1786 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001787 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001788 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001789 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001790 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001791 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001792 ha_alert("Cannot load configuration file/directory %s : %s\n",
1793 *argv,
1794 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001795 exit(1);
1796 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001797 break;
Willy Tarreau392524d2022-02-17 18:10:36 +01001798 case 'p' :
1799 free(global.pidfile);
1800 if ((global.pidfile = strdup(*argv)) == NULL) {
1801 ha_alert("Cannot allocate memory for pidfile.\n");
1802 exit(EXIT_FAILURE);
1803 }
1804 break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001805 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806 }
1807 }
1808 }
1809 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001810 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811 argv++; argc--;
1812 }
Willy Tarreau392524d2022-02-17 18:10:36 +01001813 free(err_msg);
1814}
1815
Willy Tarreau76871a42022-03-08 16:01:40 +01001816/* call the various keyword dump functions based on the comma-delimited list of
1817 * classes in kwd_dump.
1818 */
1819static void dump_registered_keywords(void)
1820{
1821 char *end;
1822 int all __maybe_unused = 0;
1823
1824 for (; kwd_dump && *kwd_dump; kwd_dump = end) {
1825 end = strchr(kwd_dump, ',');
1826 if (end)
1827 *(end++) = 0;
1828
1829 if (strcmp(kwd_dump, "help") == 0) {
1830 printf("# List of supported keyword classes:\n");
1831 printf("all: list all keywords\n");
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001832 printf("acl: ACL keywords\n");
Willy Tarreauca1acd62022-03-29 15:02:44 +02001833 printf("cfg: configuration keywords\n");
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001834 printf("cli: CLI keywords\n");
Willy Tarreau29d799d2022-03-29 16:59:49 +02001835 printf("cnv: sample converter keywords\n");
Willy Tarreau3b65e142022-03-29 15:03:09 +02001836 printf("flt: filter names\n");
Willy Tarreauf78813f2022-03-29 16:51:29 +02001837 printf("smp: sample fetch functions\n");
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001838 printf("svc: service names\n");
Willy Tarreau76871a42022-03-08 16:01:40 +01001839 continue;
1840 }
1841 else if (strcmp(kwd_dump, "all") == 0) {
1842 all = 1;
1843 }
Willy Tarreauca1acd62022-03-29 15:02:44 +02001844
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001845 if (all || strcmp(kwd_dump, "acl") == 0) {
1846 printf("# List of registered ACL keywords:\n");
1847 acl_dump_kwd();
1848 }
1849
Willy Tarreauca1acd62022-03-29 15:02:44 +02001850 if (all || strcmp(kwd_dump, "cfg") == 0) {
1851 printf("# List of registered configuration keywords:\n");
1852 cfg_dump_registered_keywords();
1853 }
Willy Tarreau3b65e142022-03-29 15:03:09 +02001854
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001855 if (all || strcmp(kwd_dump, "cli") == 0) {
1856 printf("# List of registered CLI keywords:\n");
1857 cli_list_keywords();
1858 }
1859
Willy Tarreau29d799d2022-03-29 16:59:49 +02001860 if (all || strcmp(kwd_dump, "cnv") == 0) {
1861 printf("# List of registered sample converter functions:\n");
1862 smp_dump_conv_kw();
1863 }
1864
Willy Tarreau3b65e142022-03-29 15:03:09 +02001865 if (all || strcmp(kwd_dump, "flt") == 0) {
1866 printf("# List of registered filter names:\n");
1867 flt_dump_kws(NULL);
1868 }
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001869
Willy Tarreauf78813f2022-03-29 16:51:29 +02001870 if (all || strcmp(kwd_dump, "smp") == 0) {
1871 printf("# List of registered sample fetch functions:\n");
1872 smp_dump_fetch_kw();
1873 }
1874
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001875 if (all || strcmp(kwd_dump, "svc") == 0) {
1876 printf("# List of registered service names:\n");
1877 list_services(NULL);
1878 }
Willy Tarreau76871a42022-03-08 16:01:40 +01001879 }
1880}
1881
Willy Tarreau392524d2022-02-17 18:10:36 +01001882/*
1883 * This function initializes all the necessary variables. It only returns
1884 * if everything is OK. If something fails, it exits.
1885 */
1886static void init(int argc, char **argv)
1887{
1888 char *progname = global.log_tag.area;
1889 int err_code = 0;
1890 struct wordlist *wl;
1891 struct proxy *px;
1892 struct post_check_fct *pcf;
William Lallemandb53eb872022-04-21 18:02:53 +02001893 struct pre_check_fct *prcf;
Willy Tarreau392524d2022-02-17 18:10:36 +01001894 int ideal_maxconn;
1895
1896 if (!init_trash_buffers(1)) {
1897 ha_alert("failed to initialize trash buffers.\n");
1898 exit(1);
1899 }
1900
1901 if (init_acl() != 0)
1902 exit(1);
1903
1904 /* Initialise lua. */
1905 hlua_init();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906
Christopher Faulete3a5e352017-10-24 13:53:54 +02001907 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001908 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Willy Tarreau76871a42022-03-08 16:01:40 +01001909 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001910
William Lallemand944e6192018-11-21 15:48:31 +01001911 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001912 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001913 global.mode |= MODE_MWORKER_WAIT;
1914 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001915 }
1916
Willy Tarreau26146192021-07-21 10:01:36 +02001917 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1918 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001919 atexit_flag = 1;
1920 atexit(reexec_on_failure);
1921 }
1922
Willy Tarreau576132e2011-09-10 19:26:56 +02001923 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001924 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001925 exit(1);
1926 }
1927
Amaury Denoyelle11124302021-06-04 18:22:08 +02001928 usermsgs_clr("config");
1929
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001930 if (global.mode & MODE_CHECK_CONDITION) {
1931 int result;
1932
1933 uint32_t err;
1934 const char *errptr;
1935 char *errmsg = NULL;
1936
1937 char *args[MAX_LINE_ARGS+1];
1938 int arg = sizeof(args) / sizeof(*args);
William Lallemand89e236f2022-05-06 17:22:36 +02001939 size_t outlen;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001940 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001941
William Lallemand89e236f2022-05-06 17:22:36 +02001942 if (!check_condition)
1943 usage(progname);
1944
1945 outlen = strlen(check_condition) + 1;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001946 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001947 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001948 &errptr);
1949
1950 if (err & PARSE_ERR_QUOTE) {
1951 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1952 exit(2);
1953 }
1954
1955 if (err & PARSE_ERR_HEX) {
1956 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1957 exit(2);
1958 }
1959
1960 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1961 ha_alert("Error in condition: Line too long.\n");
1962 exit(2);
1963 }
1964
Willy Tarreauc8194c32021-07-16 16:38:58 +02001965 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001966 ha_alert("Error in condition: Too many words.\n");
1967 exit(2);
1968 }
1969
1970 if (err) {
1971 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1972 exit(2);
1973 }
1974
Willy Tarreauc8194c32021-07-16 16:38:58 +02001975 /* remerge all words into a single expression */
1976 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1977 ;
1978
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001979 result = cfg_eval_condition(args, &errmsg, &errptr);
1980
1981 if (result < 0) {
1982 if (errmsg)
1983 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1984
1985 exit(2);
1986 }
1987
1988 exit(result ? 0 : 1);
1989 }
1990
William Lallemand944e6192018-11-21 15:48:31 +01001991 /* in wait mode, we don't try to read the configuration files */
1992 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001993 char *env_cfgfiles = NULL;
1994 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001995
William Lallemand944e6192018-11-21 15:48:31 +01001996 /* handle cfgfiles that are actually directories */
1997 cfgfiles_expand_directories();
1998
1999 if (LIST_ISEMPTY(&cfg_cfgfiles))
2000 usage(progname);
2001
2002
2003 list_for_each_entry(wl, &cfg_cfgfiles, list) {
2004 int ret;
2005
Christopher Faulet4e366822021-01-12 18:57:38 +01002006 if (env_err == 0) {
2007 if (!memprintf(&env_cfgfiles, "%s%s%s",
2008 (env_cfgfiles ? env_cfgfiles : ""),
2009 (env_cfgfiles ? ";" : ""), wl->s))
2010 env_err = 1;
2011 }
William Lallemand7b302d82019-05-20 11:15:37 +02002012
William Lallemand944e6192018-11-21 15:48:31 +01002013 ret = readcfgfile(wl->s);
2014 if (ret == -1) {
2015 ha_alert("Could not open configuration file %s : %s\n",
2016 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01002017 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002018 exit(1);
2019 }
2020 if (ret & (ERR_ABORT|ERR_FATAL))
2021 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
2022 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01002023 if (err_code & ERR_ABORT) {
2024 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002025 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01002026 }
Willy Tarreauc4382422009-12-06 13:10:44 +01002027 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02002028
William Lallemand944e6192018-11-21 15:48:31 +01002029 /* do not try to resolve arguments nor to spot inconsistencies when
2030 * the configuration contains fatal errors caused by files not found
2031 * or failed memory allocations.
2032 */
2033 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2034 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01002035 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002036 exit(1);
2037 }
Christopher Faulet4e366822021-01-12 18:57:38 +01002038 if (env_err) {
2039 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
2040 exit(1);
2041 }
2042 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
2043 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02002044
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02002045 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002046 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01002047 struct mworker_proc *tmproc;
2048
William Lallemand482f9a92019-04-12 16:15:00 +02002049 setenv("HAPROXY_MWORKER", "1", 1);
2050
William Lallemand16dd1b32018-11-19 18:46:18 +01002051 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
2052
William Lallemand56be0e02022-01-28 21:11:41 +01002053 tmproc = mworker_proc_new();
William Lallemand16dd1b32018-11-19 18:46:18 +01002054 if (!tmproc) {
2055 ha_alert("Cannot allocate process structures.\n");
2056 exit(EXIT_FAILURE);
2057 }
William Lallemand8f7069a2019-04-12 16:09:23 +02002058 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01002059 tmproc->pid = pid;
2060 tmproc->timestamp = start_date.tv_sec;
William Lallemand16dd1b32018-11-19 18:46:18 +01002061 proc_self = tmproc;
2062
Willy Tarreau2b718102021-04-21 07:32:39 +02002063 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01002064 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002065
William Lallemand56be0e02022-01-28 21:11:41 +01002066 tmproc = mworker_proc_new();
Willy Tarreau6185a032021-06-15 08:02:06 +02002067 if (!tmproc) {
2068 ha_alert("Cannot allocate process structures.\n");
2069 exit(EXIT_FAILURE);
2070 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002071 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02002072
Willy Tarreau6185a032021-06-15 08:02:06 +02002073 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
2074 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02002075 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002076
2077 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01002078 }
2079 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
2080 struct wordlist *it, *c;
2081
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02002082 /* get the info of the children in the env */
2083 if (mworker_env_to_proc_list() < 0) {
2084 exit(EXIT_FAILURE);
2085 }
William Lallemande7361152018-10-26 14:47:36 +02002086
William Lallemand550db6d2018-11-06 17:37:12 +01002087 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02002088
William Lallemand550db6d2018-11-06 17:37:12 +01002089 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02002090 ha_alert("Can't create the master's CLI.\n");
2091 exit(EXIT_FAILURE);
2092 }
William Lallemande7361152018-10-26 14:47:36 +02002093
William Lallemand550db6d2018-11-06 17:37:12 +01002094 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
2095
2096 if (mworker_cli_proxy_new_listener(c->s) < 0) {
2097 ha_alert("Can't create the master's CLI.\n");
2098 exit(EXIT_FAILURE);
2099 }
Willy Tarreau2b718102021-04-21 07:32:39 +02002100 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01002101 free(c->s);
2102 free(c);
2103 }
2104 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002105 }
2106
Eric Salama5ba83352021-03-16 15:11:17 +01002107 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2108 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2109 }
2110
Christopher Faulet27c8d202021-10-13 09:50:53 +02002111 /* destroy unreferenced defaults proxies */
2112 proxy_destroy_all_unref_defaults();
2113
William Lallemandb53eb872022-04-21 18:02:53 +02002114 list_for_each_entry(prcf, &pre_check_list, list)
2115 err_code |= prcf->fct();
Willy Tarreaue90904d2021-02-12 14:08:31 +01002116
William Lallemand8b9a2df2022-05-04 14:29:46 +02002117 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2118 ha_alert("Fatal errors found in configuration.\n");
2119 exit(1);
2120 }
2121
Willy Tarreaubb925012009-07-23 13:36:36 +02002122 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002123 for (px = proxies_list; px; px = px->next) {
2124 struct server *srv;
2125 struct post_proxy_check_fct *ppcf;
2126 struct post_server_check_fct *pscf;
2127
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002128 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002129 continue;
2130
Christopher Fauletc1692962019-08-12 09:51:07 +02002131 list_for_each_entry(pscf, &post_server_check_list, list) {
2132 for (srv = px->srv; srv; srv = srv->next)
2133 err_code |= pscf->fct(srv);
2134 }
2135 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2136 err_code |= ppcf->fct(px);
2137 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002138 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002139 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002140 exit(1);
2141 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002142
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002143 err_code |= pattern_finalize_config();
2144 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2145 ha_alert("Failed to finalize pattern config.\n");
2146 exit(1);
2147 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002148
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002149 if (global.rlimit_memmax_all)
2150 global.rlimit_memmax = global.rlimit_memmax_all;
2151
Willy Tarreaue5733232019-05-22 19:24:06 +02002152#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002153 err_code |= netns_init();
2154 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002155 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002156 exit(1);
2157 }
2158#endif
2159
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002160 /* Apply server states */
2161 apply_server_state();
2162
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002163 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002164 srv_compute_all_admin_states(px);
2165
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002166 /* Apply servers' configured address */
2167 err_code |= srv_init_addr();
2168 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002169 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002170 exit(1);
2171 }
2172
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002173 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2174 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2175 exit(1);
2176 }
2177
Willy Tarreau654726d2021-12-28 15:43:11 +01002178#if defined(HA_HAVE_DUMP_LIBS)
2179 if (global.mode & MODE_DUMP_LIBS) {
2180 qfprintf(stdout, "List of loaded object files:\n");
2181 chunk_reset(&trash);
2182 if (dump_libs(&trash, 0))
2183 printf("%s", trash.area);
2184 }
2185#endif
2186
Willy Tarreau76871a42022-03-08 16:01:40 +01002187 if (global.mode & MODE_DUMP_KWD)
2188 dump_registered_keywords();
2189
Willy Tarreaubaaee002006-06-26 02:48:02 +02002190 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002191 struct peers *pr;
2192 struct proxy *px;
2193
Willy Tarreaubebd2122020-04-15 16:06:11 +02002194 if (warned & WARN_ANY)
2195 qfprintf(stdout, "Warnings were found.\n");
2196
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002197 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002198 if (pr->peers_fe)
2199 break;
2200
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002201 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002202 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002203 break;
2204
Emeric Brunbc5c8212021-08-13 09:32:50 +02002205 if (!px) {
2206 /* We may only have log-forward section */
2207 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002208 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002209 break;
2210 }
2211
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002212 if (pr || px) {
2213 /* At least one peer or one listener has been found */
2214 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002215 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002216 }
2217 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2218 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002220
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002221 if (global.mode & MODE_DIAG) {
2222 cfg_run_diagnostics();
2223 }
2224
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002225 /* Initialize the random generators */
2226#ifdef USE_OPENSSL
2227 /* Initialize SSL random generator. Must be called before chroot for
2228 * access to /dev/urandom, and before ha_random_boot() which may use
2229 * RAND_bytes().
2230 */
2231 if (!ssl_initialize_random()) {
2232 ha_alert("OpenSSL random data generator initialization failed.\n");
2233 exit(EXIT_FAILURE);
2234 }
2235#endif
2236 ha_random_boot(argv); // the argv pointer brings some kernel-fed entropy
2237
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002238 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002239 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002240
Willy Tarreaue6945732016-12-21 19:57:00 +01002241 list_for_each_entry(pcf, &post_check_list, list) {
2242 err_code |= pcf->fct();
2243 if (err_code & (ERR_ABORT|ERR_FATAL))
2244 exit(1);
2245 }
2246
William Lallemand0a012aa2022-06-21 11:11:50 +02002247 /* set the default maxconn in the master, but let it be rewritable with -n */
2248 if (global.mode & MODE_MWORKER_WAIT)
2249 global.maxconn = DEFAULT_MAXCONN;
2250
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251 if (cfg_maxconn > 0)
2252 global.maxconn = cfg_maxconn;
2253
Willy Tarreau4975d142021-03-13 11:00:33 +01002254 if (global.cli_fe)
2255 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002256
2257 if (cfg_peers) {
2258 /* peers also need to bypass global maxconn */
2259 struct peers *p = cfg_peers;
2260
2261 for (p = cfg_peers; p; p = p->next)
2262 if (p->peers_fe)
2263 global.maxsock += p->peers_fe->maxconn;
2264 }
2265
Willy Tarreaud0256482015-01-15 21:45:22 +01002266 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002267 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2268 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2269 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2270 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002271 *
2272 * If memmax is set, then it depends on which values are set. If
2273 * maxsslconn is set, we use memmax to determine how many cleartext
2274 * connections may be added, and set maxconn to the sum of the two.
2275 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2276 * the remaining amount of memory between memmax and the cleartext
2277 * connections. If neither are set, then it is considered that all
2278 * connections are SSL-capable, and maxconn is computed based on this,
2279 * then maxsslconn accordingly. We need to know if SSL is used on the
2280 * frontends, backends, or both, because when it's used on both sides,
2281 * we need twice the value for maxsslconn, but we only count the
2282 * handshake once since it is not performed on the two sides at the
2283 * same time (frontend-side is terminated before backend-side begins).
2284 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002285 * ssl_handshake_cost during its initialization. In any case, if
2286 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2287 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002288 */
Willy Tarreauac350932019-03-01 15:43:14 +01002289 ideal_maxconn = compute_ideal_maxconn();
2290
Willy Tarreaud0256482015-01-15 21:45:22 +01002291 if (!global.rlimit_memmax) {
2292 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002293 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002294 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2295 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2296 }
2297 }
2298#ifdef USE_OPENSSL
2299 else if (!global.maxconn && !global.maxsslconn &&
2300 (global.ssl_used_frontend || global.ssl_used_backend)) {
2301 /* memmax is set, compute everything automatically. Here we want
2302 * to ensure that all SSL connections will be served. We take
2303 * care of the number of sides where SSL is used, and consider
2304 * the worst case : SSL used on both sides and doing a handshake
2305 * simultaneously. Note that we can't have more than maxconn
2306 * handshakes at a time by definition, so for the worst case of
2307 * two SSL conns per connection, we count a single handshake.
2308 */
2309 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2310 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002311 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002312
Willy Tarreau2cb3be72022-05-24 07:43:57 +02002313 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002314 mem -= global.maxzlibmem;
2315 mem = mem * MEM_USABLE_RATIO;
2316
Willy Tarreau304e17e2020-03-10 17:54:54 +01002317 /* Principle: we test once to set maxconn according to the free
2318 * memory. If it results in values the system rejects, we try a
2319 * second time by respecting rlim_fd_max. If it fails again, we
2320 * go back to the initial value and will let the final code
2321 * dealing with rlimit report the error. That's up to 3 attempts.
2322 */
2323 do {
2324 global.maxconn = mem /
2325 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2326 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2327 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002328
Willy Tarreau304e17e2020-03-10 17:54:54 +01002329 if (retried == 1)
2330 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2331 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002332#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002333 if (global.maxconn > SYSTEM_MAXCONN)
2334 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002335#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002336 global.maxsslconn = sides * global.maxconn;
2337
2338 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2339 break;
2340 } while (retried++ < 2);
2341
Willy Tarreaud0256482015-01-15 21:45:22 +01002342 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2343 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2344 global.maxconn, global.maxsslconn);
2345 }
2346 else if (!global.maxsslconn &&
2347 (global.ssl_used_frontend || global.ssl_used_backend)) {
2348 /* memmax and maxconn are known, compute maxsslconn automatically.
2349 * maxsslconn being forced, we don't know how many of it will be
2350 * on each side if both sides are being used. The worst case is
2351 * when all connections use only one SSL instance because
2352 * handshakes may be on two sides at the same time.
2353 */
2354 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2355 int64_t mem = global.rlimit_memmax * 1048576ULL;
2356 int64_t sslmem;
2357
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002358 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002359 mem -= global.maxzlibmem;
2360 mem = mem * MEM_USABLE_RATIO;
2361
Willy Tarreau87b09662015-04-03 00:22:06 +02002362 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002363 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2364 global.maxsslconn = round_2dig(global.maxsslconn);
2365
2366 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002367 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2368 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2369 "without SSL is %d, but %d was found and SSL is in use.\n",
2370 global.rlimit_memmax,
2371 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2372 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002373 exit(1);
2374 }
2375
2376 if (global.maxsslconn > sides * global.maxconn)
2377 global.maxsslconn = sides * global.maxconn;
2378
2379 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2380 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2381 }
2382#endif
2383 else if (!global.maxconn) {
2384 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2385 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2386 int64_t mem = global.rlimit_memmax * 1048576ULL;
2387 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002388 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002389
2390 if (global.ssl_used_frontend || global.ssl_used_backend)
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002391 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002392
2393 mem -= global.maxzlibmem;
2394 mem = mem * MEM_USABLE_RATIO;
2395
2396 clearmem = mem;
2397 if (sides)
2398 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2399
Willy Tarreau304e17e2020-03-10 17:54:54 +01002400 /* Principle: we test once to set maxconn according to the free
2401 * memory. If it results in values the system rejects, we try a
2402 * second time by respecting rlim_fd_max. If it fails again, we
2403 * go back to the initial value and will let the final code
2404 * dealing with rlimit report the error. That's up to 3 attempts.
2405 */
2406 do {
2407 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2408 if (retried == 1)
2409 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2410 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002411#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002412 if (global.maxconn > SYSTEM_MAXCONN)
2413 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002414#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002415
Willy Tarreau304e17e2020-03-10 17:54:54 +01002416 if (clearmem <= 0 || !global.maxconn) {
2417 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2418 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2419 "is %d, but %d was found.\n",
2420 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002421 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002422 global.maxsslconn);
2423 exit(1);
2424 }
2425
2426 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2427 break;
2428 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002429
2430 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2431 if (sides && global.maxsslconn > sides * global.maxconn) {
2432 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2433 "to be limited to %d. Better reduce global.maxsslconn to get more "
2434 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2435 }
2436 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2437 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002438 }
2439
Willy Tarreaua409f302020-03-10 17:08:53 +01002440 global.maxsock = compute_ideal_maxsock(global.maxconn);
2441 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002442 if (!global.maxpipes)
2443 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444
Olivier Houchard88698d92019-04-16 19:07:22 +02002445 /* update connection pool thresholds */
2446 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2447 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2448
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002449 proxy_adjust_all_maxconn();
2450
Willy Tarreau1db37712007-06-03 17:16:49 +02002451 if (global.tune.maxpollevents <= 0)
2452 global.tune.maxpollevents = MAX_POLL_EVENTS;
2453
Willy Tarreau060a7612021-03-10 11:06:26 +01002454 if (global.tune.runqueue_depth <= 0) {
2455 /* tests on various thread counts from 1 to 64 have shown an
2456 * optimal queue depth following roughly 1/sqrt(threads).
2457 */
2458 int s = my_flsl(global.nbthread);
2459 s += (global.nbthread / s); // roughly twice the sqrt.
2460 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2461 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002462
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002463 if (global.tune.recv_enough == 0)
2464 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2465
Willy Tarreau27a674e2009-08-17 07:23:33 +02002466 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2467 global.tune.maxrewrite = global.tune.bufsize / 2;
2468
Amaury Denoyelle11124302021-06-04 18:22:08 +02002469 usermsgs_clr(NULL);
2470
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2472 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002473 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002474 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2475 }
2476
William Lallemand095ba4c2017-06-01 17:38:50 +02002477 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002478 /* command line daemon mode inhibits foreground and debug modes mode */
2479 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002480 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002482
2483 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002484
William Lallemand095ba4c2017-06-01 17:38:50 +02002485 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002486 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002487 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002488 }
2489
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002490 if (global.nbthread < 1)
2491 global.nbthread = 1;
2492
Christopher Faulet3ef26392017-08-29 16:46:57 +02002493 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002494 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002495 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002496 exit(1);
2497 }
2498
Christopher Faulet96d44832017-11-14 22:02:30 +01002499 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002500 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002501 exit(1);
2502 }
2503
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002504 /*
2505 * Note: we could register external pollers here.
2506 * Built-in pollers have been registered before main().
2507 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002508
Willy Tarreau43b78992009-01-25 15:42:27 +01002509 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002510 disable_poller("kqueue");
2511
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002512 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2513 disable_poller("evports");
2514
Willy Tarreau43b78992009-01-25 15:42:27 +01002515 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002516 disable_poller("epoll");
2517
Willy Tarreau43b78992009-01-25 15:42:27 +01002518 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002519 disable_poller("poll");
2520
Willy Tarreau43b78992009-01-25 15:42:27 +01002521 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002522 disable_poller("select");
2523
2524 /* Note: we could disable any poller by name here */
2525
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002526 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002527 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002528 fprintf(stderr, "\n");
2529 list_filters(stderr);
2530 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002531
Willy Tarreau4f60f162007-04-08 16:39:58 +02002532 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002533 ha_alert("No polling mechanism available.\n"
2534 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2535 " is too low on this platform to support maxconn and the number of listeners\n"
2536 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2537 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2538 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2539 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2540 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2541 " check build settings using 'haproxy -vv'.\n\n",
2542 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002543 exit(1);
2544 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002545 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2546 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002547 }
2548
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002549 if (!global.node)
2550 global.node = strdup(hostname);
2551
Willy Tarreau02b092f2020-10-07 18:36:54 +02002552 /* stop disabled proxies */
2553 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002554 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002555 stop_proxy(px);
2556 }
2557
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002558 if (!hlua_post_init())
2559 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560}
2561
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002562void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002564 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002565 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002566 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002567 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002568 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002569 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002570 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002571 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002572 struct per_thread_init_fct *tif, *tifb;
2573 struct per_thread_deinit_fct *tdf, *tdfb;
2574 struct per_thread_alloc_fct *taf, *tafb;
2575 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002576 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002577 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002578 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreau65009eb2022-04-27 18:02:54 +02002579 struct pre_check_fct *prcf, *prcfb;
Willy Tarreau226866e2022-04-27 18:07:24 +02002580 struct cfg_postparser *pprs, *pprsb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002581 int cur_fd;
2582
2583 /* At this point the listeners state is weird:
2584 * - most listeners are still bound and referenced in their protocol
2585 * - some might be zombies that are not in their proto anymore, but
2586 * still appear in their proxy's listeners with a valid FD.
2587 * - some might be stopped and still appear in their proxy as FD #-1
2588 * - among all of them, some might be inherited hence shared and we're
2589 * not allowed to pause them or whatever, we must just close them.
2590 * - finally some are not listeners (pipes, logs, stdout, etc) and
2591 * must be left intact.
2592 *
2593 * The safe way to proceed is to unbind (and close) whatever is not yet
2594 * unbound so that no more receiver/listener remains alive. Then close
2595 * remaining listener FDs, which correspond to zombie listeners (those
2596 * belonging to disabled proxies that were in another process).
2597 * objt_listener() would be cleaner here but not converted yet.
2598 */
2599 protocol_unbind_all();
2600
2601 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002602 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002603 continue;
2604
Willy Tarreaua74cb382020-10-15 21:29:49 +02002605 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002606 struct listener *l = fdtab[cur_fd].owner;
2607
2608 BUG_ON(l->state != LI_INIT);
2609 unbind_listener(l);
2610 }
2611 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002612
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002613 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002615 /* build a list of unique uri_auths */
2616 if (!ua)
2617 ua = p->uri_auth;
2618 else {
2619 /* check if p->uri_auth is unique */
2620 for (uap = ua; uap; uap=uap->next)
2621 if (uap == p->uri_auth)
2622 break;
2623
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002624 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002625 /* add it, if it is */
2626 p->uri_auth->next = ua;
2627 ua = p->uri_auth;
2628 }
William Lallemand0f99e342011-10-12 17:50:54 +02002629 }
2630
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002631 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002633 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002634 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002635
Christopher Faulet27c8d202021-10-13 09:50:53 +02002636 /* destroy all referenced defaults proxies */
2637 proxy_destroy_all_unref_defaults();
2638
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002639 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002640 struct stat_scope *scope, *scopep;
2641
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002642 uap = ua;
2643 ua = ua->next;
2644
Willy Tarreaua534fea2008-08-03 12:19:50 +02002645 free(uap->uri_prefix);
2646 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002647 free(uap->node);
2648 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002649
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002650 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002651 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002652
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002653 scope = uap->scope;
2654 while (scope) {
2655 scopep = scope;
2656 scope = scope->next;
2657
2658 free(scopep->px_id);
2659 free(scopep);
2660 }
2661
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002662 free(uap);
2663 }
2664
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002665 userlist_free(userlist);
2666
David Carlier834cb2e2015-09-25 12:02:25 +01002667 cfg_unregister_sections();
2668
Christopher Faulet0132d062017-07-26 15:33:35 +02002669 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002670
Willy Tarreau05554e62016-12-21 20:46:26 +01002671 list_for_each_entry(pdf, &post_deinit_list, list)
2672 pdf->fct();
2673
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002674 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002675 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002676 ha_free(&global.chroot);
Frédéric Lécaille372508c2022-05-06 08:53:16 +02002677 ha_free(&global.cluster_secret);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002678 ha_free(&global.pidfile);
2679 ha_free(&global.node);
2680 ha_free(&global.desc);
2681 ha_free(&oldpids);
2682 ha_free(&old_argv);
2683 ha_free(&localpeer);
2684 ha_free(&global.server_state_base);
2685 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002686 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002687 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002688
William Lallemand0f99e342011-10-12 17:50:54 +02002689 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002690 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002691 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002692 free(log);
2693 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002694 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002695 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002696 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002697 free(wl);
2698 }
2699
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002700 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2701 if (bol->must_free)
2702 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002703 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002704 free(bol);
2705 }
2706
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002707 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002708 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002709 free(pxdf);
2710 }
2711
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002712 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002713 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002714 free(pdf);
2715 }
2716
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002717 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002718 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002719 free(srvdf);
2720 }
2721
Tim Duesterhusfc854942020-09-10 19:46:42 +02002722 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002723 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002724 free(pcf);
2725 }
2726
Tim Duesterhus34bef072020-07-04 11:49:50 +02002727 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002728 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002729 free(pscf);
2730 }
2731
Tim Duesterhus53508d62020-09-10 19:46:40 +02002732 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002733 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002734 free(ppcf);
2735 }
2736
Willy Tarreau65009eb2022-04-27 18:02:54 +02002737 list_for_each_entry_safe(prcf, prcfb, &pre_check_list, list) {
2738 LIST_DELETE(&prcf->list);
2739 free(prcf);
2740 }
2741
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002742 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002743 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002744 free(tif);
2745 }
2746
2747 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002748 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002749 free(tdf);
2750 }
2751
2752 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002753 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002754 free(taf);
2755 }
2756
2757 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002758 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002759 free(tff);
2760 }
2761
Willy Tarreau226866e2022-04-27 18:07:24 +02002762 list_for_each_entry_safe(pprs, pprsb, &postparsers, list) {
2763 LIST_DELETE(&pprs->list);
2764 free(pprs);
2765 }
2766
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002767 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002768 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002769 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770} /* end deinit() */
2771
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002772__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002773{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002774 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002775 deinit();
2776 exit(status);
2777}
William Lallemand72160322018-11-06 17:37:16 +01002778
Willy Tarreau918ff602011-07-25 16:33:49 +02002779/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002780void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002781{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002782 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002783
Willy Tarreau55542642021-10-08 09:33:24 +02002784 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002785 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002786 wake_expired_tasks();
2787
William Lallemand1aab50b2018-06-07 09:46:01 +02002788 /* check if we caught some signals and process them in the
2789 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002790 if (signal_queue_len && tid == 0) {
2791 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002792 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002793 }
2794
2795 /* Process a few tasks */
2796 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002797
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002798 /* also stop if we failed to cleanly stop all tasks */
2799 if (killed > 1)
2800 break;
2801
Willy Tarreau10146c92015-04-13 20:44:19 +02002802 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002803 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002804 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002805 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002806 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002807 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2808 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002809 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002810 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002811 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002812 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002813 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002814 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002815
Willy Tarreau4f46a352020-03-23 09:27:28 +01002816 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002817 int i;
2818
2819 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002820 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002821 if (!(stopping_thread_mask & tid_bit)) {
2822 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2823 wake = 1;
2824 }
2825
Willy Tarreau1db42732021-04-06 11:44:07 +02002826 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002827 /* notify all threads that stopping was just set */
2828 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002829 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002830 wake_thread(i);
2831 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002832 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002833
2834 /* stop when there's nothing left to do */
2835 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002836 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2837 /* wake all threads waiting on jobs==0 */
2838 for (i = 0; i < global.nbthread; i++)
2839 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2840 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002841 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002842 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002843 }
2844
Willy Tarreauc49ba522019-12-11 08:12:23 +01002845 /* If we have to sleep, measure how long */
2846 next = wake ? TICK_ETERNITY : next_timer_expiry();
2847
Willy Tarreau58b458d2008-06-29 22:40:23 +02002848 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002849 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002850
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002851 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002852 }
2853}
2854
Christopher Faulet1d17c102017-08-29 15:38:48 +02002855static void *run_thread_poll_loop(void *data)
2856{
Willy Tarreau082b6282019-05-22 14:42:12 +02002857 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002858 struct per_thread_init_fct *ptif;
2859 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002860 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002861 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002862 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2863 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002864
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002865 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002866 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002867 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002868
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002869 /* Now, initialize one thread init at a time. This is better since
2870 * some init code is a bit tricky and may release global resources
2871 * after reallocating them locally. This will also ensure there is
2872 * no race on file descriptors allocation.
2873 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002874#ifdef USE_THREAD
2875 pthread_mutex_lock(&init_mutex);
2876#endif
2877 /* The first thread must set the number of threads left */
2878 if (!init_left)
2879 init_left = global.nbthread;
2880 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002881
Willy Tarreau55542642021-10-08 09:33:24 +02002882 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002883
Willy Tarreau082b6282019-05-22 14:42:12 +02002884 /* per-thread alloc calls performed here are not allowed to snoop on
2885 * other threads, so they are free to initialize at their own rhythm
2886 * as long as they act as if they were alone. None of them may rely
2887 * on resources initialized by the other ones.
2888 */
2889 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2890 if (!ptaf->fct()) {
2891 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002892#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002893 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002894#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002895 exit(1);
2896 }
2897 }
2898
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002899 /* per-thread init calls performed here are not allowed to snoop on
2900 * other threads, so they are free to initialize at their own rhythm
2901 * as long as they act as if they were alone.
2902 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002903 list_for_each_entry(ptif, &per_thread_init_list, list) {
2904 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002905 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002906#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002907 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002908#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002909 exit(1);
2910 }
2911 }
2912
Willy Tarreau71092822019-06-10 09:51:04 +02002913 /* enabling protocols will result in fd_insert() calls to be performed,
2914 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002915 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002916 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002917 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002918 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002919
Willy Tarreau34a150c2019-06-11 09:16:41 +02002920#ifdef USE_THREAD
2921 pthread_cond_broadcast(&init_cond);
2922 pthread_mutex_unlock(&init_mutex);
2923
2924 /* now wait for other threads to finish starting */
2925 pthread_mutex_lock(&init_mutex);
2926 while (init_left)
2927 pthread_cond_wait(&init_cond, &init_mutex);
2928 pthread_mutex_unlock(&init_mutex);
2929#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002930
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002931#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2932 /* Let's refrain from using setuid executables. This way the impact of
2933 * an eventual vulnerability in a library remains limited. It may
2934 * impact external checks but who cares about them anyway ? In the
2935 * worst case it's possible to disable the option. Obviously we do this
2936 * in workers only. We can't hard-fail on this one as it really is
2937 * implementation dependent though we're interested in feedback, hence
2938 * the warning.
2939 */
2940 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2941 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002942 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 +01002943 ha_warning("Failed to disable setuid, please report to developers with detailed "
2944 "information about your operating system. You can silence this warning "
2945 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2946 }
2947 }
2948#endif
2949
Willy Tarreaud96f1122019-12-03 07:07:36 +01002950#if defined(RLIMIT_NPROC)
2951 /* all threads have started, it's now time to prevent any new thread
2952 * or process from starting. Obviously we do this in workers only. We
2953 * can't hard-fail on this one as it really is implementation dependent
2954 * though we're interested in feedback, hence the warning.
2955 */
2956 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2957 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2958 static int warn_fail;
2959
Willy Tarreau18515722021-04-06 11:57:41 +02002960 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002961 ha_warning("Failed to disable forks, please report to developers with detailed "
2962 "information about your operating system. You can silence this warning "
2963 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2964 }
2965 }
2966#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002967 run_poll_loop();
2968
2969 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2970 ptdf->fct();
2971
Willy Tarreau082b6282019-05-22 14:42:12 +02002972 list_for_each_entry(ptff, &per_thread_free_list, list)
2973 ptff->fct();
2974
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002975#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002976 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002977 if (tid > 0)
2978 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002979#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002980 return NULL;
2981}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002982
William Dauchyf9af9d72019-11-17 15:47:16 +01002983/* set uid/gid depending on global settings */
2984static void set_identity(const char *program_name)
2985{
2986 if (global.gid) {
2987 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2988 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2989 " without 'uid'/'user' is generally useless.\n", program_name);
2990
2991 if (setgid(global.gid) == -1) {
2992 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2993 protocol_unbind_all();
2994 exit(1);
2995 }
2996 }
2997
2998 if (global.uid && setuid(global.uid) == -1) {
2999 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
3000 protocol_unbind_all();
3001 exit(1);
3002 }
3003}
3004
Willy Tarreaubaaee002006-06-26 02:48:02 +02003005int main(int argc, char **argv)
3006{
3007 int err, retry;
3008 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02003009 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02003010 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
3011
3012 /* Catch forced CFLAGS that miss 2-complement integer overflow */
3013 if (intovf + 0x7FFFFFFF >= intovf) {
3014 fprintf(stderr,
3015 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
3016 "The source code was miscompiled by the compiler, which usually indicates that\n"
3017 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
3018 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
3019 "and INSTALL files to decide on the best way to pass your local build options.\n"
3020 "\nBuild options :"
3021#ifdef BUILD_TARGET
3022 "\n TARGET = " BUILD_TARGET
3023#endif
3024#ifdef BUILD_CPU
3025 "\n CPU = " BUILD_CPU
3026#endif
3027#ifdef BUILD_CC
3028 "\n CC = " BUILD_CC
3029#endif
3030#ifdef BUILD_CFLAGS
3031 "\n CFLAGS = " BUILD_CFLAGS
3032#endif
3033#ifdef BUILD_OPTIONS
3034 "\n OPTIONS = " BUILD_OPTIONS
3035#endif
3036#ifdef BUILD_DEBUG
3037 "\n DEBUG = " BUILD_DEBUG
3038#endif
3039 "\n\n");
3040 return 1;
3041 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003042
Olivier Houchard5fa300d2018-02-03 15:15:21 +01003043 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003044
Willy Tarreaubf696402019-03-01 10:09:28 +01003045 /* take a copy of initial limits before we possibly change them */
3046 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02003047
3048 if (limit.rlim_max == RLIM_INFINITY)
3049 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01003050 rlim_fd_cur_at_boot = limit.rlim_cur;
3051 rlim_fd_max_at_boot = limit.rlim_max;
3052
Willy Tarreau5794fb02018-11-25 18:43:29 +01003053 /* process all initcalls in order of potential dependency */
3054 RUN_INITCALLS(STG_PREPARE);
3055 RUN_INITCALLS(STG_LOCK);
Willy Tarreau3ebe4d92022-02-18 14:51:49 +01003056 RUN_INITCALLS(STG_REGISTER);
Willy Tarreau34527d52022-02-17 17:45:58 +01003057
3058 /* now's time to initialize early boot variables */
3059 init_early(argc, argv);
3060
Willy Tarreau18f96d02022-02-23 17:25:00 +01003061 /* handles argument parsing */
3062 init_args(argc, argv);
3063
Willy Tarreau5794fb02018-11-25 18:43:29 +01003064 RUN_INITCALLS(STG_ALLOC);
3065 RUN_INITCALLS(STG_POOL);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003066 RUN_INITCALLS(STG_INIT);
3067
Willy Tarreau34527d52022-02-17 17:45:58 +01003068 /* this is the late init where the config is parsed */
Emeric Bruncf20bf12010-10-22 16:06:11 +02003069 init(argc, argv);
Willy Tarreau34527d52022-02-17 17:45:58 +01003070
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003071 signal_register_fct(SIGQUIT, dump, SIGQUIT);
3072 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
3073 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02003074 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075
Willy Tarreaue437c442010-03-17 18:02:46 +01003076 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
3077 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
3078 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003080 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081
Willy Tarreaudc23a922011-02-16 11:10:36 +01003082 /* ulimits */
3083 if (!global.rlimit_nofile)
3084 global.rlimit_nofile = global.maxsock;
3085
3086 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01003087 limit.rlim_cur = global.rlimit_nofile;
3088 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
3089
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003090 if ((global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) ||
3091 setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02003092 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003093 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3094 limit.rlim_cur = global.fd_hard_limit;
3095
William Dauchy0fec3ab2019-10-27 20:08:11 +01003096 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3097 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
3098 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003099 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003100 }
3101 else {
3102 /* try to set it to the max possible at least */
3103 limit.rlim_cur = limit.rlim_max;
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003104 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3105 limit.rlim_cur = global.fd_hard_limit;
3106
William Dauchy0fec3ab2019-10-27 20:08:11 +01003107 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
3108 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02003109
William Dauchya5194602020-03-28 19:29:58 +01003110 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003111 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
3112 global.rlimit_nofile = limit.rlim_cur;
3113 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01003114 }
3115 }
3116
3117 if (global.rlimit_memmax) {
3118 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01003119 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01003120#ifdef RLIMIT_AS
3121 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003122 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3123 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3124 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003125 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003126 }
3127 else
William Dauchya5194602020-03-28 19:29:58 +01003128 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003129 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003130 }
3131#else
3132 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003133 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3134 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3135 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003136 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003137 }
3138 else
William Dauchya5194602020-03-28 19:29:58 +01003139 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003140 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003141 }
3142#endif
3143 }
3144
William Lallemandf82afbb2022-01-07 18:19:42 +01003145 /* Try to get the listeners FD from the previous process using
3146 * _getsocks on the stat socket, it must never been done in wait mode
3147 * and check mode
3148 */
3149 if (old_unixsocket &&
3150 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK|MODE_CHECK_CONDITION))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003151 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003152 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003153 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003154 if (!(global.mode & MODE_MWORKER))
3155 exit(1);
3156 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003157 }
3158 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003159
Willy Tarreaubaaee002006-06-26 02:48:02 +02003160 /* We will loop at most 100 times with 10 ms delay each time.
3161 * That's at most 1 second. We only send a signal to old pids
3162 * if we cannot grab at least one port.
3163 */
3164 retry = MAX_START_RETRIES;
3165 err = ERR_NONE;
3166 while (retry >= 0) {
3167 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003168 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003169 /* exit the loop on no error or fatal error */
3170 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003171 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003172 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 break;
3174
3175 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3176 * listening sockets. So on those platforms, it would be wiser to
3177 * simply send SIGUSR1, which will not be undoable.
3178 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003179 if (tell_old_pids(SIGTTOU) == 0) {
3180 /* no need to wait if we can't contact old pids */
3181 retry = 0;
3182 continue;
3183 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 /* give some time to old processes to stop listening */
3185 w.tv_sec = 0;
3186 w.tv_usec = 10*1000;
3187 select(0, NULL, NULL, NULL, &w);
3188 retry--;
3189 }
3190
Willy Tarreaue91bff22020-09-02 11:11:43 +02003191 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003192 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003193 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003194 if (retry != MAX_START_RETRIES && nb_oldpids) {
3195 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 exit(1);
3199 }
3200
William Lallemand944e6192018-11-21 15:48:31 +01003201 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003202 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 /* Note: we don't have to send anything to the old pids because we
3204 * never stopped them. */
3205 exit(1);
3206 }
3207
Willy Tarreaue91bff22020-09-02 11:11:43 +02003208 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003209 * the previous process gave us, we don't need them anymore
3210 */
Willy Tarreaub5101162022-01-28 18:28:18 +01003211 sock_drop_unused_old_sockets();
Willy Tarreaudd815982007-10-16 12:25:14 +02003212
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003214 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3215 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003216
Willy Tarreaubaaee002006-06-26 02:48:02 +02003217 /* MODE_QUIET can inhibit alerts and warnings below this line */
3218
PiBa-NL149a81a2017-12-25 21:03:31 +01003219 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3220 /* either stdin/out/err are already closed or should stay as they are. */
3221 if ((global.mode & MODE_DAEMON)) {
3222 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3223 global.mode &= ~MODE_VERBOSE;
3224 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3225 }
3226 } else {
3227 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3228 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003229 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231 }
3232
3233 /* open log & pid files before the chroot */
William Lallemand7b820a62022-02-14 09:02:14 +01003234 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) &&
3235 !(global.mode & MODE_MWORKER_WAIT) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236 unlink(global.pidfile);
3237 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3238 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003239 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 if (nb_oldpids)
3241 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003242 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 exit(1);
3244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 }
3246
Willy Tarreaub38651a2007-03-24 17:24:39 +01003247 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003248 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3249 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003250 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003251 exit(1);
3252 }
3253
Jackie Tapia749f74c2020-07-22 18:59:40 -05003254 /* If the user is not root, we'll still let them try the configuration
3255 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003256 */
3257 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003258 ha_warning("[%s.main()] Some options which require full privileges"
3259 " might not work well.\n"
3260 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003261
William Lallemand095ba4c2017-06-01 17:38:50 +02003262 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3263
3264 /* chroot if needed */
3265 if (global.chroot != NULL) {
3266 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003267 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003268 if (nb_oldpids)
3269 tell_old_pids(SIGTTIN);
3270 protocol_unbind_all();
3271 exit(1);
3272 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003273 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003274 }
3275
William Lallemand944e6192018-11-21 15:48:31 +01003276 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003277 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278
William Lallemand27edc4b2019-05-07 17:49:33 +02003279 /* send a SIGTERM to workers who have a too high reloads number */
3280 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3281 mworker_kill_max_reloads(SIGTERM);
3282
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 /* Note that any error at this stage will be fatal because we will not
3284 * be able to restart the old pids.
3285 */
3286
William Dauchyf9af9d72019-11-17 15:47:16 +01003287 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3288 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003289
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 /* check ulimits */
3291 limit.rlim_cur = limit.rlim_max = 0;
3292 getrlimit(RLIMIT_NOFILE, &limit);
3293 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003294 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3295 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3296 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3297 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3298 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003299 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003300 }
3301 else
3302 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003303 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003304 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3305 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003306 }
3307
William Lallemand944e6192018-11-21 15:48:31 +01003308 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003310 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003311 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003312
William Lallemand095ba4c2017-06-01 17:38:50 +02003313 /*
3314 * if daemon + mworker: must fork here to let a master
3315 * process live in background before forking children
3316 */
William Lallemand73b85e72017-06-01 17:38:51 +02003317
3318 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3319 && (global.mode & MODE_MWORKER)
3320 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003321 ret = fork();
3322 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003323 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003324 protocol_unbind_all();
3325 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003326 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003327 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003328 } else /* change the process group ID in the child (master process) */
3329 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003330 }
William Lallemande20b6a62017-06-01 17:38:55 +02003331
William Lallemande20b6a62017-06-01 17:38:55 +02003332
William Lallemanddeed7802017-11-06 11:00:04 +01003333 /* if in master-worker mode, write the PID of the father */
3334 if (global.mode & MODE_MWORKER) {
3335 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003336 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003337 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003338 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003339 }
3340
Willy Tarreaubaaee002006-06-26 02:48:02 +02003341 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003342 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003343 if (global.mode & MODE_MWORKER)
3344 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003345
3346 ret = fork();
3347 if (ret < 0) {
3348 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3349 protocol_unbind_all();
3350 exit(1); /* there has been an error */
3351 }
3352 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003353 /* This one must not be exported, it's internal! */
3354 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003355 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003356 }
3357 else { /* parent here */
3358 in_parent = 1;
3359
William Lallemand944e6192018-11-21 15:48:31 +01003360 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3361 char pidstr[100];
3362 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003363 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003364 }
3365 if (global.mode & MODE_MWORKER) {
3366 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003367
William Lallemand5d71a6b2021-11-09 15:25:31 +01003368 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003369 /* find the right mworker_proc */
3370 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003371 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003372 child->timestamp = now.tv_sec;
3373 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003374 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003375 break;
3376 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003377 }
3378 }
William Lallemand944e6192018-11-21 15:48:31 +01003379 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003380
William Lallemand944e6192018-11-21 15:48:31 +01003381 } else {
3382 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003383 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003385
3386#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003387 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 +02003388
David CARLIERdf91cbd2022-01-06 18:53:50 +00003389#if defined(CPUSET_USE_CPUSET) || defined(__DragonFly__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003390 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003391 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
David CARLIERdf91cbd2022-01-06 18:53:50 +00003392#elif defined(__FreeBSD__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003393 struct hap_cpuset *set = &cpu_map.proc;
David CARLIERdf91cbd2022-01-06 18:53:50 +00003394 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003395#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003396 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003397#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003399 if (pidfd >= 0) {
3400 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3401 close(pidfd);
3402 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003403
3404 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003405 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406
Willy Tarreaud67ff342021-06-15 07:58:09 +02003407 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003408 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003409 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003410
3411 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3412 (global.mode & MODE_DAEMON)) {
3413 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003414 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3415 stdio_quiet(-1);
3416
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003417 global.mode &= ~MODE_VERBOSE;
3418 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003419 }
3420
William Lallemandfab0fdc2021-11-09 18:01:22 +01003421 if (global.mode & MODE_MWORKER_WAIT) {
3422 /* only the wait mode handles the master CLI */
3423 mworker_loop();
3424 } else {
3425
3426 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand836bda22021-11-09 18:16:47 +01003427 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003428 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003429 mworker_reexec_waitmode();
3430 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003431 /* should never get there */
3432 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003433 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003434#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003435 ssl_free_dh();
3436#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003437 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003438 }
3439
William Lallemandcb11fd22017-06-01 17:38:52 +02003440 /* child must never use the atexit function */
3441 atexit_flag = 0;
3442
William Lallemandbc193052018-09-11 10:06:26 +02003443 /* close useless master sockets */
3444 if (global.mode & MODE_MWORKER) {
3445 struct mworker_proc *child, *it;
3446 master = 0;
3447
William Lallemand309dc9a2018-10-26 14:47:45 +02003448 mworker_cli_proxy_stop();
3449
William Lallemandbc193052018-09-11 10:06:26 +02003450 /* free proc struct of other processes */
3451 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003452 /* close the FD of the master side for all
3453 * workers, we don't need to close the worker
3454 * side of other workers since it's done with
3455 * the bind_proc */
William Lallemand7e018782022-01-28 21:56:24 +01003456 if (child->ipc_fd[0] >= 0) {
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003457 close(child->ipc_fd[0]);
William Lallemand7e018782022-01-28 21:56:24 +01003458 child->ipc_fd[0] = -1;
3459 }
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003460 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003461 child->reloads == 0) {
3462 /* keep this struct if this is our pid */
3463 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003464 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003465 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003466 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003467 mworker_free_child(child);
3468 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003469 }
3470 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003471
William Lallemande1340412017-12-28 16:09:36 +01003472 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3473 devnullfd = open("/dev/null", O_RDWR, 0);
3474 if (devnullfd < 0) {
3475 ha_alert("Cannot open /dev/null\n");
3476 exit(EXIT_FAILURE);
3477 }
3478 }
3479
William Lallemand095ba4c2017-06-01 17:38:50 +02003480 /* Must chroot and setgid/setuid in the children */
3481 /* chroot if needed */
3482 if (global.chroot != NULL) {
3483 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003484 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003485 if (nb_oldpids)
3486 tell_old_pids(SIGTTIN);
3487 protocol_unbind_all();
3488 exit(1);
3489 }
3490 }
3491
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003492 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003493 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003494
William Lallemand7f80eb22017-05-26 18:19:55 +02003495 /* pass through every cli socket, and check if it's bound to
3496 * the current process and if it exposes listeners sockets.
3497 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3498 * */
3499
Willy Tarreau4975d142021-03-13 11:00:33 +01003500 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003501 struct bind_conf *bind_conf;
3502
Willy Tarreau4975d142021-03-13 11:00:33 +01003503 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003504 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003505 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3506 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003507 }
3508 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003509 }
3510
William Lallemand2e8fad92018-11-13 16:18:23 +01003511 /*
3512 * This is only done in daemon mode because we might want the
3513 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3514 * we should now close the 3 first FDs to ensure that we can
3515 * detach from the TTY. We MUST NOT do it in other cases since
3516 * it would have already be done, and 0-2 would have been
3517 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003519 if ((global.mode & MODE_DAEMON) &&
3520 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003521 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003522 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003523 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3525 }
3526 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003527 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3528 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003529 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003530 }
3531
William Dauchye039f262019-11-17 15:47:15 +01003532 /* try our best to re-enable core dumps depending on system capabilities.
3533 * What is addressed here :
3534 * - remove file size limits
3535 * - remove core size limits
3536 * - mark the process dumpable again if it lost it due to user/group
3537 */
3538 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3539 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3540
3541#if defined(RLIMIT_FSIZE)
3542 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3543 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3544 ha_alert("[%s.main()] Failed to set the raise the maximum "
3545 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003546 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003547 }
3548 else
3549 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003550 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003551 }
3552#endif
3553
3554#if defined(RLIMIT_CORE)
3555 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3556 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3557 ha_alert("[%s.main()] Failed to set the raise the core "
3558 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003559 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003560 }
3561 else
3562 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003563 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003564 }
3565#endif
3566
3567#if defined(USE_PRCTL)
3568 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3569 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3570 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003571#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003572 {
3573 int traceable = PROC_TRACE_CTL_ENABLE;
3574 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3575 ha_warning("[%s.main()] Failed to set the traceable flag, "
3576 "no core will be dumped.\n", argv[0]);
3577 }
William Dauchye039f262019-11-17 15:47:15 +01003578#endif
3579 }
3580
Christopher Faulete3a5e352017-10-24 13:53:54 +02003581 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003582 reset_usermsgs_ctx();
3583
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003584 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003585 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003586
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003587 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003588 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003589
3590 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003591 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003592
3593 /* wait for all threads to terminate */
3594 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003595
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003596 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597}
3598
Willy Tarreaubaaee002006-06-26 02:48:02 +02003599/*
3600 * Local variables:
3601 * c-indent-level: 8
3602 * c-basic-offset: 8
3603 * End:
3604 */