blob: adb9a7a4d7abe11bd496b55f9be3f9141d889554 [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>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200118#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200119#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200120#include <haproxy/pool.h>
121#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200122#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200123#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200124#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200125#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200126#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200127#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200128#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200129#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200130#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200131#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200132#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200133#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200134#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200135#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200136#include <haproxy/time.h>
137#include <haproxy/tools.h>
138#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200139#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200140#include <haproxy/version.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200141
Willy Tarreaubaaee002006-06-26 02:48:02 +0200142
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100143/* array of init calls for older platforms */
144DECLARE_INIT_STAGES;
145
Willy Tarreauf4596402021-04-10 16:53:05 +0200146/* create a read_mostly section to hold variables which are accessed a lot
147 * but which almost never change. The purpose is to isolate them in their
148 * own cache lines where they don't risk to be perturbated by write accesses
149 * to neighbor variables. We need to create an empty aligned variable for
150 * this. The fact that the variable is of size zero means that it will be
151 * eliminated at link time if no other variable uses it, but alignment will
152 * be respected.
153 */
154empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
155
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200156#ifdef BUILD_FEATURES
157const char *build_features = BUILD_FEATURES;
158#else
159const char *build_features = "";
160#endif
161
Willy Tarreau477ecd82010-01-03 21:12:30 +0100162/* list of config files */
163static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164int pid; /* current process id */
165
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100166volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100167volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100168
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169/* global options */
170struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100171 .hard_stop_after = TICK_ETERNITY,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100172 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100173 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200174 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200175 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
William Lallemand9d5f5482012-11-07 16:12:57 +0100176 .maxzlibmem = 0,
William Lallemandd85f9172012-11-09 17:05:39 +0100177 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100178 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200179 .unix_bind = {
180 .ux = {
181 .uid = -1,
182 .gid = -1,
183 .mode = 0,
184 }
185 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200186 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100187 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100188 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100189 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100190 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200191 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200192 .pool_low_ratio = 20,
193 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200194 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200195#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100196 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200197#endif
William Lallemandf3747832012-11-09 12:33:10 +0100198 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100199#ifdef DEFAULT_IDLE_TIMER
200 .idle_timer = DEFAULT_IDLE_TIMER,
201#else
202 .idle_timer = 1000, /* 1 second */
203#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200204 },
Emeric Brun76d88952012-10-05 15:47:31 +0200205#ifdef USE_OPENSSL
206#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200207 .maxsslconn = DEFAULT_MAXSSLCONN,
208#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200209#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210 /* others NULL OK */
211};
212
213/*********************************************************************/
214
215int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100216int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200217int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100218int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100219int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100220int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreau392524d2022-02-17 18:10:36 +0100221int arg_mode = 0; /* MODE_DEBUG etc as passed on command line ... */
222char *change_dir = NULL; /* set when -C is passed */
223char *check_condition = NULL; /* check condition passed to -cc */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500225/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 * or kill. We will send them a signal every 10 ms until we can bind to all
227 * our ports. With 200 retries, that's about 2 seconds.
228 */
229#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230static int *oldpids = NULL;
231static int oldpids_sig; /* use USR1 or TERM */
232
Olivier Houchardf73629d2017-04-05 22:33:04 +0200233/* Path to the unix socket we use to retrieve listener sockets from the old process */
234static const char *old_unixsocket;
235
William Lallemandcb11fd22017-06-01 17:38:52 +0200236int atexit_flag = 0;
237
Willy Tarreaubb545b42010-08-25 12:58:59 +0200238int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239const int zero = 0;
240const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200241const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100243char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200244char *localpeer = NULL;
Willy Tarreau76871a42022-03-08 16:01:40 +0100245static char *kwd_dump = NULL; // list of keyword dumps to produce
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246
William Lallemand00417412020-06-05 14:08:41 +0200247static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200248
William Lallemandbc193052018-09-11 10:06:26 +0200249struct list proc_list = LIST_HEAD_INIT(proc_list);
250
251int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100252unsigned int rlim_fd_cur_at_boot = 0;
253unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200254
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100255/* per-boot randomness */
256unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
257
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200258/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200259static void *run_thread_poll_loop(void *data);
260
Willy Tarreauff055502014-04-28 22:27:06 +0200261/* bitfield of a few warnings to emit just once (WARN_*) */
262unsigned int warned = 0;
263
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200264/* set if experimental features have been used for the current process */
Willy Tarreauedd42682022-02-25 10:10:00 +0100265unsigned int tainted = 0;
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200266
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200267unsigned int experimental_directives_allowed = 0;
268
269int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
270 char **errmsg)
271{
272 if (kw->flags & KWF_EXPERIMENTAL) {
273 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200274 memprintf(errmsg, "parsing [%s:%d] : '%s' directive is experimental, must be allowed via a global 'expose-experimental-directives'",
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200275 file, linenum, kw->kw);
276 return 1;
277 }
278 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
279 }
280
281 return 0;
282}
283
William Lallemande7361152018-10-26 14:47:36 +0200284/* master CLI configuration (-S flag) */
285struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100286
287/* These are strings to be reported in the output of "haproxy -vv". They may
288 * either be constants (in which case must_free must be zero) or dynamically
289 * allocated strings to pass to free() on exit, and in this case must_free
290 * must be non-zero.
291 */
292struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
293struct build_opts_str {
294 struct list list;
295 const char *str;
296 int must_free;
297};
298
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299/*********************************************************************/
300/* general purpose functions ***************************************/
301/*********************************************************************/
302
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100303/* used to register some build option strings at boot. Set must_free to
304 * non-zero if the string must be freed upon exit.
305 */
306void hap_register_build_opts(const char *str, int must_free)
307{
308 struct build_opts_str *b;
309
310 b = calloc(1, sizeof(*b));
311 if (!b) {
312 fprintf(stderr, "out of memory\n");
313 exit(1);
314 }
315 b->str = str;
316 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200317 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100318}
319
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200320#define VERSION_MAX_ELTS 7
321
322/* This function splits an haproxy version string into an array of integers.
323 * The syntax of the supported version string is the following:
324 *
325 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
326 *
327 * This validates for example:
328 * 1.2.1-pre2, 1.2.1, 1.2.10.1, 1.3.16-rc1, 1.4-dev3, 1.5-dev18, 1.5-dev18-43
329 * 2.4-dev18-f6818d-20
330 *
331 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
332 * one fixed place in the array. The tags take a numeric value called <e> which
333 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
334 * considered as zero (henxe 1.5 and 1.5.0 are the same).
335 *
336 * The resulting values are:
337 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
338 * 1.2.1 1, 2, 1, 0, 3, 0, 0
339 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
340 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
341 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
342 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
343 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
344 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
345 *
346 * The function returns non-zero if the conversion succeeded, or zero if it
347 * failed.
348 */
349int split_version(const char *version, unsigned int *value)
350{
351 const char *p, *s;
352 char *error;
353 int nelts;
354
355 /* Initialize array with zeroes */
356 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
357 value[nelts] = 0;
358 value[4] = 3;
359
360 p = version;
361
362 /* If the version number is empty, return false */
363 if (*p == '\0')
364 return 0;
365
366 /* Convert first number <a> */
367 value[0] = strtol(p, &error, 10);
368 p = error + 1;
369 if (*error == '\0')
370 return 1;
371 if (*error == '-')
372 goto split_version_tag;
373 if (*error != '.')
374 return 0;
375
376 /* Convert first number <b> */
377 value[1] = strtol(p, &error, 10);
378 p = error + 1;
379 if (*error == '\0')
380 return 1;
381 if (*error == '-')
382 goto split_version_tag;
383 if (*error != '.')
384 return 0;
385
386 /* Convert first number <c> */
387 value[2] = strtol(p, &error, 10);
388 p = error + 1;
389 if (*error == '\0')
390 return 1;
391 if (*error == '-')
392 goto split_version_tag;
393 if (*error != '.')
394 return 0;
395
396 /* Convert first number <d> */
397 value[3] = strtol(p, &error, 10);
398 p = error + 1;
399 if (*error == '\0')
400 return 1;
401 if (*error != '-')
402 return 0;
403
404 split_version_tag:
405 /* Check for commit number */
406 if (*p >= '0' && *p <= '9')
407 goto split_version_commit;
408
409 /* Read tag */
410 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
411 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
412 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
413 else
414 goto split_version_commit;
415
416 /* Convert tag number */
417 value[5] = strtol(p, &error, 10);
418 p = error + 1;
419 if (*error == '\0')
420 return 1;
421 if (*error != '-')
422 return 0;
423
424 split_version_commit:
425 /* Search the last "-" */
426 s = strrchr(p, '-');
427 if (s) {
428 s++;
429 if (*s == '\0')
430 return 0;
431 value[6] = strtol(s, &error, 10);
432 if (*error != '\0')
433 value[6] = 0;
434 return 1;
435 }
436
437 /* convert the version */
438 value[6] = strtol(p, &error, 10);
439 if (*error != '\0')
440 value[6] = 0;
441
442 return 1;
443}
444
445/* This function compares the current haproxy version with an arbitrary version
446 * string. It returns:
447 * -1 : the version in argument is older than the current haproxy version
448 * 0 : the version in argument is the same as the current haproxy version
449 * 1 : the version in argument is newer than the current haproxy version
450 *
451 * Or some errors:
452 * -2 : the current haproxy version is not parsable
453 * -3 : the version in argument is not parsable
454 */
455int compare_current_version(const char *version)
456{
457 unsigned int loc[VERSION_MAX_ELTS];
458 unsigned int mod[VERSION_MAX_ELTS];
459 int i;
460
461 /* split versions */
462 if (!split_version(haproxy_version, loc))
463 return -2;
464 if (!split_version(version, mod))
465 return -3;
466
467 /* compare versions */
468 for (i = 0; i < VERSION_MAX_ELTS; i++) {
469 if (mod[i] < loc[i])
470 return -1;
471 else if (mod[i] > loc[i])
472 return 1;
473 }
474 return 0;
475}
476
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100477static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200479 struct utsname utsname;
480
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200481 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100482 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100483
484 if (strlen(PRODUCT_URL_BUGS) > 0) {
485 char base_version[20];
486 int dots = 0;
487 char *del;
488
489 /* only retrieve the base version without distro-specific extensions */
490 for (del = haproxy_version; *del; del++) {
491 if (*del == '.')
492 dots++;
493 else if (*del < '0' || *del > '9')
494 break;
495 }
496
497 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
498 if (dots < 2)
499 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
500 else
501 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
502 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200503
504 if (uname(&utsname) == 0) {
505 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200507}
508
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100509static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100510{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100511 struct build_opts_str *item;
512
Willy Tarreau7b066db2007-12-02 11:28:59 +0100513 printf("Build options :"
514#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100515 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100516#endif
517#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100518 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100519#endif
520#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100521 "\n CC = " BUILD_CC
522#endif
523#ifdef BUILD_CFLAGS
524 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100525#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100526#ifdef BUILD_OPTIONS
527 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100528#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100529#ifdef BUILD_DEBUG
530 "\n DEBUG = " BUILD_DEBUG
531#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100532#ifdef BUILD_FEATURES
533 "\n\nFeature list : " BUILD_FEATURES
534#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200535 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100536 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200537 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100538 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200539
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100540 list_for_each_entry(item, &build_opts_list, list) {
541 puts(item->str);
542 }
543
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100544 putchar('\n');
545
Willy Tarreaube5b6852009-10-03 18:57:08 +0200546 list_pollers(stdout);
547 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200548 list_mux_proto(stdout);
549 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100550 list_services(stdout);
551 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100552 list_filters(stdout);
553 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100554}
555
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556/*
557 * This function prints the command line usage and exits
558 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100559static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560{
561 display_version();
562 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200563 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200564 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200565 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100566 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreauf4b79c42022-02-23 15:20:53 +0100568 " -dM[<byte>,help,...] debug memory (default: poison with <byte>/0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200569 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200570 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200571 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100572#if defined(USE_SYSTEMD)
573 " -Ws master-worker mode with systemd notify support.\n"
574#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200576 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200577 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100578 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 " -m limits the usable amount of memory (in MB)\n"
580 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200581 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200583#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200584 " -de disables epoll() usage even when available\n"
585#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200586#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200587 " -dk disables kqueue() usage even when available\n"
588#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200589#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000590 " -dv disables event ports usage even when available\n"
591#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200592#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200593 " -dp disables poll() usage even when available\n"
594#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200595#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100596 " -dS disables splice usage (broken on old kernels)\n"
597#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200598#if defined(USE_GETADDRINFO)
599 " -dG disables getaddrinfo() usage\n"
600#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000601#if defined(SO_REUSEPORT)
602 " -dR disables SO_REUSEPORT usage\n"
603#endif
Willy Tarreau654726d2021-12-28 15:43:11 +0100604#if defined(HA_HAVE_DUMP_LIBS)
605 " -dL dumps loaded object files after config checks\n"
606#endif
Willy Tarreau76871a42022-03-08 16:01:40 +0100607 " -dK{class[,...]} dump registered keywords (use 'help' for list)\n"
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100608 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100609 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200610 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200611 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200612 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200613 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200614 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100616 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 exit(1);
618}
619
620
621
622/*********************************************************************/
623/* more specific functions ***************************************/
624/*********************************************************************/
625
William Lallemand73b85e72017-06-01 17:38:51 +0200626/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
627 * pids the signal was correctly delivered to.
628 */
William Lallemande25473c2019-04-01 11:29:56 +0200629int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200630{
631 int p;
632 int ret = 0;
633 for (p = 0; p < nb_oldpids; p++)
634 if (kill(oldpids[p], sig) == 0)
635 ret++;
636 return ret;
637}
638
William Lallemand75ea0a02017-11-15 19:02:58 +0100639/*
William Lallemand73b85e72017-06-01 17:38:51 +0200640 * remove a pid forom the olpid array and decrease nb_oldpids
641 * return 1 pid was found otherwise return 0
642 */
643
644int delete_oldpid(int pid)
645{
646 int i;
647
648 for (i = 0; i < nb_oldpids; i++) {
649 if (oldpids[i] == pid) {
650 oldpids[i] = oldpids[nb_oldpids - 1];
651 oldpids[nb_oldpids - 1] = 0;
652 nb_oldpids--;
653 return 1;
654 }
655 }
656 return 0;
657}
658
William Lallemand85b0bd92017-06-01 17:38:53 +0200659
William Lallemand73b85e72017-06-01 17:38:51 +0200660/*
661 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800662 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200663 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100664static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200665{
William Lallemand00417412020-06-05 14:08:41 +0200666 char **next_argv = NULL;
667 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200668 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200669 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200670 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100671 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100672 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200673
674 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100675#if defined(USE_SYSTEMD)
676 if (global.tune.options & GTUNE_USE_SYSTEMD)
677 sd_notify(0, "RELOADING=1");
678#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200679 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
680
William Lallemand55a921c2022-01-28 21:17:30 +0100681 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200682 mworker_proc_list_to_env(); /* put the children description in the env */
683
William Lallemandc4810b82021-11-18 10:51:30 +0100684 /* ensure that we close correctly every listeners before reexecuting */
685 mworker_cleanlisteners();
686
William Lallemand7c756a82018-11-26 11:53:40 +0100687 /* during the reload we must ensure that every FDs that can't be
688 * reuse (ie those that are not referenced in the proc_list)
689 * are closed or they will leak. */
690
691 /* close the listeners FD */
692 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200693
William Lallemand67e371e2021-11-25 10:03:44 +0100694 if (fdtab)
695 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100696
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500697#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200698 /* close random device FDs */
699 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100700#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100701
Willy Tarreau8dca1952019-03-01 10:21:55 +0100702 /* restore the initial FD limits */
703 limit.rlim_cur = rlim_fd_cur_at_boot;
704 limit.rlim_max = rlim_fd_max_at_boot;
705 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
706 getrlimit(RLIMIT_NOFILE, &limit);
707 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
708 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
709 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
710 }
711
William Lallemand73b85e72017-06-01 17:38:51 +0200712 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200713 while (old_argv[old_argc])
714 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200715
William Lallemand85b0bd92017-06-01 17:38:53 +0200716 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200717 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200718 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200719 if (next_argv == NULL)
720 goto alloc_error;
721
William Lallemand00417412020-06-05 14:08:41 +0200722 /* copy the program name */
723 next_argv[next_argc++] = old_argv[0];
724
725 /* insert the new options just after argv[0] in case we have a -- */
726
William Lallemandbefab9e2021-11-25 00:49:19 +0100727 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
728 /* add -sf <PID>* to argv */
729 if (mworker_child_nb() > 0) {
730 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200731
William Lallemandbefab9e2021-11-25 00:49:19 +0100732 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200733
William Lallemandbefab9e2021-11-25 00:49:19 +0100734 list_for_each_entry(child, &proc_list, list) {
735 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
736 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100737
William Lallemandbefab9e2021-11-25 00:49:19 +0100738 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
739 continue;
740 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
741 goto alloc_error;
742 msg = NULL;
743 }
William Lallemand73b85e72017-06-01 17:38:51 +0200744 }
William Lallemand2be557f2021-11-24 18:45:37 +0100745
746 if (current_child) {
747 /* add the -x option with the socketpair of the current worker */
748 next_argv[next_argc++] = "-x";
749 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
750 goto alloc_error;
751 msg = NULL;
752 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200753 }
754
William Lallemand00417412020-06-05 14:08:41 +0200755 /* copy the previous options */
756 for (i = 1; i < old_argc; i++)
757 next_argv[next_argc++] = old_argv[i];
758
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200759 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100760 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100761 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100762 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100763 return;
764
William Lallemand73b85e72017-06-01 17:38:51 +0200765alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100766 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800767 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200768 return;
769}
770
William Lallemandfab0fdc2021-11-09 18:01:22 +0100771/* reexec haproxy in waitmode */
772static void mworker_reexec_waitmode()
773{
774 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
775 mworker_reexec();
776}
777
778/* reload haproxy and emit a warning */
779void mworker_reload()
780{
William Lallemandad221f42021-11-09 18:43:59 +0100781 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100782 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100783
William Lallemand836bda22021-11-09 18:16:47 +0100784 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100785
William Lallemandefd95472021-11-26 14:43:57 +0100786 /* close the poller FD and the thread waker pipe FD */
787 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
788 ptdf->fct();
789
William Lallemandad221f42021-11-09 18:43:59 +0100790 /* increment the number of reloads */
791 list_for_each_entry(child, &proc_list, list) {
792 child->reloads++;
793 }
794
William Lallemandfab0fdc2021-11-09 18:01:22 +0100795 mworker_reexec();
796}
797
William Lallemandb3f2be32018-09-11 10:06:18 +0200798static void mworker_loop()
799{
800
801#if defined(USE_SYSTEMD)
802 if (global.tune.options & GTUNE_USE_SYSTEMD)
803 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
804#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200805 /* Busy polling makes no sense in the master :-) */
806 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200807
William Lallemandbc193052018-09-11 10:06:26 +0200808
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100809 signal_unregister(SIGTTIN);
810 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100811 signal_unregister(SIGUSR1);
812 signal_unregister(SIGHUP);
813 signal_unregister(SIGQUIT);
814
William Lallemandb3f2be32018-09-11 10:06:18 +0200815 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
816 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100817 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
818 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200819 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
820 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
821 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
822 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
823
824 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100825 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200826
William Lallemandbc193052018-09-11 10:06:26 +0200827 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
828 some SIGCHLD were lost */
829
William Lallemandb3f2be32018-09-11 10:06:18 +0200830 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200831
William Lallemand2672eb92018-12-14 15:52:39 +0100832#ifdef USE_THREAD
833 tid_bit = 1;
834 all_threads_mask = 1;
835#endif
836
William Lallemandb3f2be32018-09-11 10:06:18 +0200837 jobs++; /* this is the "master" job, we want to take care of the
838 signals even if there is no listener so the poll loop don't
839 leave */
840
841 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200842 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200843}
William Lallemandcb11fd22017-06-01 17:38:52 +0200844
845/*
846 * Reexec the process in failure mode, instead of exiting
847 */
848void reexec_on_failure()
849{
William Lallemand68836742021-11-10 10:49:06 +0100850 struct mworker_proc *child;
851
William Lallemandcb11fd22017-06-01 17:38:52 +0200852 if (!atexit_flag)
853 return;
William Lallemand68836742021-11-10 10:49:06 +0100854
855 /* get the info of the children in the env */
856 if (mworker_env_to_proc_list() < 0) {
857 exit(EXIT_FAILURE);
858 }
859
860 /* increment the number of failed reloads */
861 list_for_each_entry(child, &proc_list, list) {
862 child->failedreloads++;
863 }
864
Willy Tarreaue08acae2022-01-28 18:40:06 +0100865 /* do not keep unused FDs retrieved from the previous process */
866 sock_drop_unused_old_sockets();
867
William Lallemandfab0fdc2021-11-09 18:01:22 +0100868 usermsgs_clr(NULL);
William Lallemand836bda22021-11-09 18:16:47 +0100869 ha_warning("Loading failure!\n");
William Lallemandfab0fdc2021-11-09 18:01:22 +0100870 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200871}
William Lallemand73b85e72017-06-01 17:38:51 +0200872
873
874/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200875 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
876 * a signal zero to all subscribers. This means that it's as easy as
877 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100879static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200880{
881 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200882 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100883 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884}
885
886/*
887 * upon SIGTTOU, we pause everything
888 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100889static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200890{
Willy Tarreau775e0012020-09-24 16:36:26 +0200891 if (protocol_pause_all() & ERR_FATAL) {
892 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200893 ha_warning("%s", msg);
894 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200895 soft_stop();
896 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100897 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898}
899
900/*
901 * upon SIGTTIN, let's have a soft stop.
902 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100903static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904{
Willy Tarreau775e0012020-09-24 16:36:26 +0200905 if (protocol_resume_all() & ERR_FATAL) {
906 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 +0200907 ha_warning("%s", msg);
908 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200909 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910}
911
912/*
913 * this function dumps every server's state when the process receives SIGHUP.
914 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100915static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100917 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918
Christopher Faulet767a84b2017-11-24 16:50:31 +0100919 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920 while (p) {
921 struct server *s = p->srv;
922
923 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
924 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100925 chunk_printf(&trash,
926 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
927 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200928 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200929 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200930 ha_warning("%s\n", trash.area);
931 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 s = s->next;
933 }
934
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200935 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
936 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100937 chunk_printf(&trash,
938 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
939 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200940 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 +0200941 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100942 chunk_printf(&trash,
943 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
944 p->id,
945 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200946 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 +0200947 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100948 chunk_printf(&trash,
949 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
950 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
951 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200952 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 +0200953 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200954 ha_warning("%s\n", trash.area);
955 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200956
957 p = p->next;
958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959}
960
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100961static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200963 /* dump memory usage then free everything possible */
964 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100965 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200966}
967
William Lallemande1340412017-12-28 16:09:36 +0100968/*
969 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
970 * If <fd> < 0, it opens /dev/null and use it to dup
971 *
972 * In the case of chrooting, you have to open /dev/null before the chroot, and
973 * pass the <fd> to this function
974 */
975static void stdio_quiet(int fd)
976{
977 if (fd < 0)
978 fd = open("/dev/null", O_RDWR, 0);
979
980 if (fd > -1) {
981 fclose(stdin);
982 fclose(stdout);
983 fclose(stderr);
984
985 dup2(fd, 0);
986 dup2(fd, 1);
987 dup2(fd, 2);
988 if (fd > 2)
989 close(fd);
990 return;
991 }
992
993 ha_alert("Cannot open /dev/null\n");
994 exit(EXIT_FAILURE);
995}
996
997
Joseph Herlant03420902018-11-15 10:41:50 -0800998/* This function checks if cfg_cfgfiles contains directories.
999 * If it finds one, it adds all the files (and only files) it contains
1000 * in cfg_cfgfiles in place of the directory (and removes the directory).
1001 * It adds the files in lexical order.
1002 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001003 * It doesn't add files with name starting with '.'
1004 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001005static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001006{
1007 struct wordlist *wl, *wlb;
1008 char *err = NULL;
1009
1010 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1011 struct stat file_stat;
1012 struct dirent **dir_entries = NULL;
1013 int dir_entries_nb;
1014 int dir_entries_it;
1015
1016 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001017 ha_alert("Cannot open configuration file/directory %s : %s\n",
1018 wl->s,
1019 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001020 exit(1);
1021 }
1022
1023 if (!S_ISDIR(file_stat.st_mode))
1024 continue;
1025
1026 /* from this point wl->s is a directory */
1027
1028 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1029 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001030 ha_alert("Cannot open configuration directory %s : %s\n",
1031 wl->s,
1032 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001033 exit(1);
1034 }
1035
1036 /* for each element in the directory wl->s */
1037 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1038 struct dirent *dir_entry = dir_entries[dir_entries_it];
1039 char *filename = NULL;
1040 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1041
1042 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001043 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001044 */
1045 if (dir_entry->d_name[0] == '.' ||
1046 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1047 goto next_dir_entry;
1048
1049 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001050 ha_alert("Cannot load configuration files %s : out of memory.\n",
1051 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001052 exit(1);
1053 }
1054
1055 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001056 ha_alert("Cannot open configuration file %s : %s\n",
1057 wl->s,
1058 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001059 exit(1);
1060 }
1061
1062 /* don't add anything else than regular file in cfg_cfgfiles
1063 * this way we avoid loops
1064 */
1065 if (!S_ISREG(file_stat.st_mode))
1066 goto next_dir_entry;
1067
1068 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001069 ha_alert("Cannot load configuration files %s : %s\n",
1070 filename,
1071 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001072 exit(1);
1073 }
1074
1075next_dir_entry:
1076 free(filename);
1077 free(dir_entry);
1078 }
1079
1080 free(dir_entries);
1081
1082 /* remove the current directory (wl) from cfg_cfgfiles */
1083 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001084 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001085 free(wl);
1086 }
1087
1088 free(err);
1089}
1090
Willy Tarreaubaaee002006-06-26 02:48:02 +02001091/*
William Lallemand73b85e72017-06-01 17:38:51 +02001092 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001093 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001094 * Return an allocated copy of argv
1095 */
1096
1097static char **copy_argv(int argc, char **argv)
1098{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001099 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001100
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001101 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001102 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001103 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001104 return NULL;
1105 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001106 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001107
William Lallemanddf6c5a82020-06-04 17:40:23 +02001108 /* first copy argv[0] */
1109 *newargv++ = *argv++;
1110 argc--;
1111
1112 while (argc > 0) {
1113 if (**argv != '-') {
1114 /* non options are copied but will fail in the argument parser */
1115 *newargv++ = *argv++;
1116 argc--;
1117
1118 } else {
1119 char *flag;
1120
1121 flag = *argv + 1;
1122
1123 if (flag[0] == '-' && flag[1] == 0) {
1124 /* "--\0" copy every arguments till the end of argv */
1125 *newargv++ = *argv++;
1126 argc--;
1127
1128 while (argc > 0) {
1129 *newargv++ = *argv++;
1130 argc--;
1131 }
1132 } else {
1133 switch (*flag) {
1134 case 's':
1135 /* -sf / -st and their parameters are ignored */
1136 if (flag[1] == 'f' || flag[1] == 't') {
1137 argc--;
1138 argv++;
1139 /* The list can't contain a negative value since the only
1140 way to know the end of this list is by looking for the
1141 next option or the end of the options */
1142 while (argc > 0 && argv[0][0] != '-') {
1143 argc--;
1144 argv++;
1145 }
William Lallemand398da622020-09-02 16:12:23 +02001146 } else {
1147 argc--;
1148 argv++;
1149
William Lallemanddf6c5a82020-06-04 17:40:23 +02001150 }
1151 break;
1152
1153 case 'x':
1154 /* this option and its parameter are ignored */
1155 argc--;
1156 argv++;
1157 if (argc > 0) {
1158 argc--;
1159 argv++;
1160 }
1161 break;
1162
1163 case 'C':
1164 case 'n':
1165 case 'm':
1166 case 'N':
1167 case 'L':
1168 case 'f':
1169 case 'p':
1170 case 'S':
1171 /* these options have only 1 parameter which must be copied and can start with a '-' */
1172 *newargv++ = *argv++;
1173 argc--;
1174 if (argc == 0)
1175 goto error;
1176 *newargv++ = *argv++;
1177 argc--;
1178 break;
1179 default:
1180 /* for other options just copy them without parameters, this is also done
1181 * for options like "--foo", but this will fail in the argument parser.
1182 * */
1183 *newargv++ = *argv++;
1184 argc--;
1185 break;
1186 }
William Lallemand73b85e72017-06-01 17:38:51 +02001187 }
1188 }
William Lallemand73b85e72017-06-01 17:38:51 +02001189 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001190
William Lallemanddf6c5a82020-06-04 17:40:23 +02001191 return retargv;
1192
1193error:
1194 free(retargv);
1195 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001196}
1197
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001198
1199/* Performs basic random seed initialization. The main issue with this is that
1200 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1201 * which means that there will only be 4 billion possible random sequences once
1202 * srandom() is called, regardless of the internal state. Not calling it is
1203 * even worse as we'll always produce the same randoms sequences. What we do
1204 * here is to create an initial sequence from various entropy sources, hash it
1205 * using SHA1 and keep the resulting 160 bits available globally.
1206 *
1207 * We initialize the current process with the first 32 bits before starting the
1208 * polling loop, where all this will be changed to have process specific and
1209 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001210 *
1211 * Before starting threads, it's still possible to call random() as srandom()
1212 * is initialized from this, but after threads and/or processes are started,
1213 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001214 */
1215static void ha_random_boot(char *const *argv)
1216{
1217 unsigned char message[256];
1218 unsigned char *m = message;
1219 struct timeval tv;
1220 blk_SHA_CTX ctx;
1221 unsigned long l;
1222 int fd;
1223 int i;
1224
1225 /* start with current time as pseudo-random seed */
1226 gettimeofday(&tv, NULL);
1227 write_u32(m, tv.tv_sec); m += 4;
1228 write_u32(m, tv.tv_usec); m += 4;
1229
1230 /* PID and PPID add some OS-based randomness */
1231 write_u16(m, getpid()); m += 2;
1232 write_u16(m, getppid()); m += 2;
1233
1234 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1235 fd = open("/dev/urandom", O_RDONLY);
1236 if (fd >= 0) {
1237 i = read(fd, m, 20);
1238 if (i > 0)
1239 m += i;
1240 close(fd);
1241 }
1242
1243 /* take up to 160 bits bytes from openssl (non-blocking) */
1244#ifdef USE_OPENSSL
1245 if (RAND_bytes(m, 20) == 1)
1246 m += 20;
1247#endif
1248
1249 /* take 160 bits from existing random in case it was already initialized */
1250 for (i = 0; i < 5; i++) {
1251 write_u32(m, random());
1252 m += 4;
1253 }
1254
1255 /* stack address (benefit form operating system's ASLR) */
1256 l = (unsigned long)&m;
1257 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1258
1259 /* argv address (benefit form operating system's ASLR) */
1260 l = (unsigned long)&argv;
1261 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1262
1263 /* use tv_usec again after all the operations above */
1264 gettimeofday(&tv, NULL);
1265 write_u32(m, tv.tv_usec); m += 4;
1266
1267 /*
1268 * At this point, ~84-92 bytes have been used
1269 */
1270
1271 /* finish with the hostname */
1272 strncpy((char *)m, hostname, message + sizeof(message) - m);
1273 m += strlen(hostname);
1274
1275 /* total message length */
1276 l = m - message;
1277
1278 memset(&ctx, 0, sizeof(ctx));
1279 blk_SHA1_Init(&ctx);
1280 blk_SHA1_Update(&ctx, message, l);
1281 blk_SHA1_Final(boot_seed, &ctx);
1282
1283 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001284 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001285}
1286
Willy Tarreau5a023f02019-03-01 14:19:31 +01001287/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1288 * setting, and returns it. It may return -1 meaning "unlimited" if some
1289 * unlimited proxies have been found and the global.maxconn value is not yet
1290 * set. It may also return a value greater than maxconn if it's not yet set.
1291 * Note that a value of zero means there is no need for pipes. -1 is never
1292 * returned if global.maxconn is valid.
1293 */
1294static int compute_ideal_maxpipes()
1295{
1296 struct proxy *cur;
1297 int nbfe = 0, nbbe = 0;
1298 int unlimited = 0;
1299 int pipes;
1300 int max;
1301
1302 for (cur = proxies_list; cur; cur = cur->next) {
1303 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1304 if (cur->cap & PR_CAP_FE) {
1305 max = cur->maxconn;
1306 nbfe += max;
1307 if (!max) {
1308 unlimited = 1;
1309 break;
1310 }
1311 }
1312 if (cur->cap & PR_CAP_BE) {
1313 max = cur->fullconn ? cur->fullconn : global.maxconn;
1314 nbbe += max;
1315 if (!max) {
1316 unlimited = 1;
1317 break;
1318 }
1319 }
1320 }
1321 }
1322
1323 pipes = MAX(nbfe, nbbe);
1324 if (global.maxconn) {
1325 if (pipes > global.maxconn || unlimited)
1326 pipes = global.maxconn;
1327 } else if (unlimited) {
1328 pipes = -1;
1329 }
1330
1331 return pipes >= 4 ? pipes / 4 : pipes;
1332}
1333
Willy Tarreauac350932019-03-01 15:43:14 +01001334/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1335 * rlimits and computes an ideal maxconn. It's meant to be called only when
1336 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001337 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1338 * default 100) is returned as it is expected that it will even run on tight
1339 * environments, and will maintain compatibility with previous packages that
1340 * used to rely on this value as the default one. The system will emit a
1341 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001342 */
1343static int compute_ideal_maxconn()
1344{
1345 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1346 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1347 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001348 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001349 int maxconn;
1350
1351 /* we have to take into account these elements :
1352 * - number of engine_fds, which inflates the number of FD needed per
1353 * connection by this number.
1354 * - number of pipes per connection on average : for the unlimited
1355 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1356 * fixed value of 2*pipes.
1357 * - two FDs per connection
1358 */
1359
1360 /* subtract listeners and checks */
1361 remain -= global.maxsock;
1362
Willy Tarreau3f200852019-03-14 19:13:17 +01001363 /* one epoll_fd/kqueue_fd per thread */
1364 remain -= global.nbthread;
1365
1366 /* one wake-up pipe (2 fd) per thread */
1367 remain -= 2 * global.nbthread;
1368
Willy Tarreauac350932019-03-01 15:43:14 +01001369 /* Fixed pipes values : we only subtract them if they're not larger
1370 * than the remaining FDs because pipes are optional.
1371 */
1372 if (pipes >= 0 && pipes * 2 < remain)
1373 remain -= pipes * 2;
1374
1375 if (pipes < 0) {
1376 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1377 * = maxconn * (2 + 0.5 + engine_fds)
1378 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1379 */
1380 maxconn = 2 * remain / (5 + 2 * engine_fds);
1381 } else {
1382 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1383 * = maxconn * (2 + engine_fds)
1384 */
1385 maxconn = remain / (2 + engine_fds);
1386 }
1387
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001388 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001389}
1390
Willy Tarreaua409f302020-03-10 17:08:53 +01001391/* computes the estimated maxsock value for the given maxconn based on the
1392 * possibly set global.maxpipes and existing partial global.maxsock. It may
1393 * temporarily change global.maxconn for the time needed to propagate the
1394 * computations, and will reset it.
1395 */
1396static int compute_ideal_maxsock(int maxconn)
1397{
1398 int maxpipes = global.maxpipes;
1399 int maxsock = global.maxsock;
1400
1401
1402 if (!maxpipes) {
1403 int old_maxconn = global.maxconn;
1404
1405 global.maxconn = maxconn;
1406 maxpipes = compute_ideal_maxpipes();
1407 global.maxconn = old_maxconn;
1408 }
1409
1410 maxsock += maxconn * 2; /* each connection needs two sockets */
1411 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1412 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1413 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1414
1415 /* compute fd used by async engines */
1416 if (global.ssl_used_async_engines) {
1417 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1418
1419 maxsock += maxconn * sides * global.ssl_used_async_engines;
1420 }
1421 return maxsock;
1422}
1423
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001424/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001425 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1426 * value is accepted, non-zero otherwise. This is used to determine if an
1427 * automatic limit may be applied or not. When it is not, the caller knows that
1428 * the highest we can do is the rlim_max at boot. In case of error, we return
1429 * that the setting is possible, so that we defer the error processing to the
1430 * final stage in charge of enforcing this.
1431 */
1432static int check_if_maxsock_permitted(int maxsock)
1433{
1434 struct rlimit orig_limit, test_limit;
1435 int ret;
1436
1437 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1438 return 1;
1439
1440 /* don't go further if we can't even set to what we have */
1441 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1442 return 1;
1443
1444 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1445 test_limit.rlim_cur = test_limit.rlim_max;
1446 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1447
1448 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1449 return 1;
1450
1451 return ret == 0;
1452}
1453
Willy Tarreau34527d52022-02-17 17:45:58 +01001454/* This performs th every basic early initialization at the end of the PREPARE
1455 * init stage. It may only assume that list heads are initialized, but not that
1456 * anything else is correct. It will initialize a number of variables that
1457 * depend on command line and will pre-parse the command line. If it fails, it
1458 * directly exits.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001460static void init_early(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461{
Kevinm48936af2010-12-22 16:08:21 +00001462 char *progname;
Willy Tarreau34527d52022-02-17 17:45:58 +01001463 char *tmp;
1464 int len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001465
Willy Tarreau34527d52022-02-17 17:45:58 +01001466 /* First, let's initialize most global variables */
1467 totalconn = actconn = listeners = stopping = 0;
1468 killed = pid = 0;
1469
1470 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
1471 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Christopher Faulete3a5e352017-10-24 13:53:54 +02001472 global.mode = MODE_STARTING;
William Lallemand73b85e72017-06-01 17:38:51 +02001473
Willy Tarreau34527d52022-02-17 17:45:58 +01001474 /* if we were in mworker mode, we should restart in mworker mode */
1475 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1476 global.mode |= MODE_MWORKER;
David du Colombier7af46052012-05-16 14:16:48 +02001477
Willy Tarreau34527d52022-02-17 17:45:58 +01001478 /* initialize date, time, and pid */
1479 tzset();
1480 clock_init_process_date();
1481 start_date = now;
1482 pid = getpid();
1483
1484 /* Set local host name and adjust some environment variables.
1485 * NB: POSIX does not make it mandatory for gethostname() to
1486 * NULL-terminate the string in case of truncation, and at least
1487 * FreeBSD appears not to do it.
Emeric Brun2b920a12010-09-23 18:30:22 +02001488 */
1489 memset(hostname, 0, sizeof(hostname));
1490 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001491
Willy Tarreau34527d52022-02-17 17:45:58 +01001492 /* preset some environment variables */
1493 localpeer = strdup(hostname);
1494 if (!localpeer || setenv("HAPROXY_LOCALPEER", localpeer, 1) < 0) {
Dragan Dosen4f014152020-06-18 16:56:47 +02001495 ha_alert("Cannot allocate memory for local peer.\n");
1496 exit(EXIT_FAILURE);
1497 }
Emeric Brun2b920a12010-09-23 18:30:22 +02001498
Willy Tarreau34527d52022-02-17 17:45:58 +01001499 /* Initialize the random generators */
1500#ifdef USE_OPENSSL
1501 /* Initialize SSL random generator. Must be called before chroot for
1502 * access to /dev/urandom, and before ha_random_boot() which may use
1503 * RAND_bytes().
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001505 if (!ssl_initialize_random()) {
1506 ha_alert("OpenSSL random data generator initialization failed.\n");
1507 exit(EXIT_FAILURE);
1508 }
1509#endif
1510 ha_random_boot(argv); // the argv pointer brings some kernel-fed entropy
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001511
Willy Tarreau34527d52022-02-17 17:45:58 +01001512 /* Some CPU affinity stuff may have to be initialized */
1513#ifdef USE_CPU_AFFINITY
1514 {
1515 int i;
1516 ha_cpuset_zero(&cpu_map.proc);
1517 ha_cpuset_zero(&cpu_map.proc_t1);
1518 for (i = 0; i < MAX_THREADS; ++i) {
1519 ha_cpuset_zero(&cpu_map.thread[i]);
1520 }
1521 }
1522#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001523
Willy Tarreau34527d52022-02-17 17:45:58 +01001524 /* extract the program name from argv[0], it will be used for the logs
1525 * and error messages.
1526 */
1527 progname = *argv;
1528 while ((tmp = strchr(progname, '/')) != NULL)
1529 progname = tmp + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530
Willy Tarreau34527d52022-02-17 17:45:58 +01001531 len = strlen(progname);
1532 progname = strdup(progname);
1533 if (!progname) {
1534 ha_alert("Cannot allocate memory for log_tag.\n");
1535 exit(EXIT_FAILURE);
1536 }
Willy Tarreau84310e22014-02-14 11:59:04 +01001537
Willy Tarreau34527d52022-02-17 17:45:58 +01001538 chunk_initlen(&global.log_tag, progname, len, len);
1539}
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001540
Willy Tarreau392524d2022-02-17 18:10:36 +01001541/* handles program arguments. Very minimal parsing is performed, variables are
1542 * fed with some values, and lists are completed with other ones. In case of
1543 * error, it will exit.
Willy Tarreau34527d52022-02-17 17:45:58 +01001544 */
Willy Tarreau392524d2022-02-17 18:10:36 +01001545static void init_args(int argc, char **argv)
Willy Tarreau34527d52022-02-17 17:45:58 +01001546{
Willy Tarreau34527d52022-02-17 17:45:58 +01001547 char *progname = global.log_tag.area;
Willy Tarreau392524d2022-02-17 18:10:36 +01001548 char *err_msg = NULL;
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001549
Willy Tarreau34527d52022-02-17 17:45:58 +01001550 /* pre-fill in the global tuning options before we let the cmdline
1551 * change them.
1552 */
Willy Tarreau43b78992009-01-25 15:42:27 +01001553 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001554#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001555 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001557#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001558 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001560#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001561 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001562#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001563#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001564 global.tune.options |= GTUNE_USE_EVPORTS;
1565#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001566#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001567 global.tune.options |= GTUNE_USE_SPLICE;
1568#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001569#if defined(USE_GETADDRINFO)
1570 global.tune.options |= GTUNE_USE_GAI;
1571#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001572#if defined(SO_REUSEPORT)
1573 global.tune.options |= GTUNE_USE_REUSEPORT;
1574#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001575#ifdef USE_THREAD
1576 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1577#endif
William Dauchya5194602020-03-28 19:29:58 +01001578 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579
Willy Tarreau392524d2022-02-17 18:10:36 +01001580 /* keep a copy of original arguments for the master process */
1581 old_argv = copy_argv(argc, argv);
1582 if (!old_argv) {
1583 ha_alert("failed to copy argv.\n");
1584 exit(EXIT_FAILURE);
1585 }
1586
1587 /* skip program name and start */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 argc--; argv++;
1589 while (argc > 0) {
1590 char *flag;
1591
1592 if (**argv == '-') {
1593 flag = *argv+1;
1594
1595 /* 1 arg */
1596 if (*flag == 'v') {
1597 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001598 if (flag[1] == 'v') /* -vv */
1599 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600 exit(0);
1601 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001602#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001604 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001606#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001608 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001610#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001611 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001612 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001613#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001614#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001615 else if (*flag == 'd' && flag[1] == 'v')
1616 global.tune.options &= ~GTUNE_USE_EVPORTS;
1617#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001618#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001619 else if (*flag == 'd' && flag[1] == 'S')
1620 global.tune.options &= ~GTUNE_USE_SPLICE;
1621#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001622#if defined(USE_GETADDRINFO)
1623 else if (*flag == 'd' && flag[1] == 'G')
1624 global.tune.options &= ~GTUNE_USE_GAI;
1625#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001626#if defined(SO_REUSEPORT)
1627 else if (*flag == 'd' && flag[1] == 'R')
1628 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1629#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001630 else if (*flag == 'd' && flag[1] == 'V')
1631 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632 else if (*flag == 'V')
1633 arg_mode |= MODE_VERBOSE;
1634 else if (*flag == 'd' && flag[1] == 'b')
1635 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001636 else if (*flag == 'd' && flag[1] == 'D')
1637 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001638 else if (*flag == 'd' && flag[1] == 'W')
1639 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreauef301b72022-02-23 14:15:18 +01001640 else if (*flag == 'd' && flag[1] == 'M') {
Willy Tarreau1408b1f2022-02-18 18:54:40 +01001641 int ret = pool_parse_debugging(flag + 2, &err_msg);
1642
1643 if (ret <= -1) {
1644 if (ret < -1)
1645 ha_alert("-dM: %s\n", err_msg);
1646 else
1647 printf("%s\n", err_msg);
1648 ha_free(&err_msg);
1649 exit(ret < -1 ? EXIT_FAILURE : 0);
1650 } else if (ret == 0) {
1651 ha_warning("-dM: %s\n", err_msg);
1652 ha_free(&err_msg);
1653 }
Willy Tarreauef301b72022-02-23 14:15:18 +01001654 }
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001655 else if (*flag == 'd' && flag[1] == 'r')
1656 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001657#if defined(HA_HAVE_DUMP_LIBS)
1658 else if (*flag == 'd' && flag[1] == 'L')
1659 arg_mode |= MODE_DUMP_LIBS;
1660#endif
Willy Tarreau76871a42022-03-08 16:01:40 +01001661 else if (*flag == 'd' && flag[1] == 'K') {
1662 arg_mode |= MODE_DUMP_KWD;
1663 kwd_dump = flag + 2;
1664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 else if (*flag == 'd')
1666 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001667 else if (*flag == 'c' && flag[1] == 'c') {
1668 arg_mode |= MODE_CHECK_CONDITION;
1669 argv++;
1670 argc--;
1671 check_condition = *argv;
1672 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 else if (*flag == 'c')
1674 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001675 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001676 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001677 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001678 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001679#if defined(USE_SYSTEMD)
1680 global.tune.options |= GTUNE_USE_SYSTEMD;
1681#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001682 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 +01001683 usage(progname);
1684#endif
1685 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001686 else if (*flag == 'W')
1687 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688 else if (*flag == 'q')
1689 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001690 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001691 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001692 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001693 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001694 }
William Lallemand4fc09692017-06-19 16:37:19 +02001695 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001696 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001697 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001698
Olivier Houchardf73629d2017-04-05 22:33:04 +02001699 argv++;
1700 argc--;
1701 }
William Lallemande7361152018-10-26 14:47:36 +02001702 else if (*flag == 'S') {
1703 struct wordlist *c;
1704
William Lallemanda6b32492020-06-04 23:49:20 +02001705 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001706 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1707 usage(progname);
1708 }
1709 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1710 ha_alert("Cannot allocate memory\n");
1711 exit(EXIT_FAILURE);
1712 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001713 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001714
1715 argv++;
1716 argc--;
1717 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1719 /* list of pids to finish ('f') or terminate ('t') */
1720
1721 if (flag[1] == 'f')
1722 oldpids_sig = SIGUSR1; /* finish then exit */
1723 else
1724 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001725 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001726 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001727 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1728 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001729 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001730 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001732 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001733 errno = 0;
1734 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1735 if (errno) {
1736 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1737 flag,
1738 *argv, strerror(errno));
1739 exit(1);
1740 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001741 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001742 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001743 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1744 flag, endptr);
1745 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001746 }
Chris Lane236062f2018-02-05 23:15:44 +00001747 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001748 if (oldpids[nb_oldpids] <= 0)
1749 usage(progname);
1750 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001751 }
1752 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001753 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1754 /* now that's a cfgfile list */
1755 argv++; argc--;
1756 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001757 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001758 ha_alert("Cannot load configuration file/directory %s : %s\n",
1759 *argv,
1760 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001761 exit(1);
1762 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001763 argv++; argc--;
1764 }
1765 break;
1766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767 else { /* >=2 args */
1768 argv++; argc--;
1769 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001770 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771
1772 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001773 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001775 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001777 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001778 free(localpeer);
1779 if ((localpeer = strdup(*argv)) == NULL) {
1780 ha_alert("Cannot allocate memory for local peer.\n");
1781 exit(EXIT_FAILURE);
1782 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001783 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001784 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001785 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001786 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001787 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001788 ha_alert("Cannot load configuration file/directory %s : %s\n",
1789 *argv,
1790 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001791 exit(1);
1792 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001793 break;
Willy Tarreau392524d2022-02-17 18:10:36 +01001794 case 'p' :
1795 free(global.pidfile);
1796 if ((global.pidfile = strdup(*argv)) == NULL) {
1797 ha_alert("Cannot allocate memory for pidfile.\n");
1798 exit(EXIT_FAILURE);
1799 }
1800 break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001801 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802 }
1803 }
1804 }
1805 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001806 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807 argv++; argc--;
1808 }
Willy Tarreau392524d2022-02-17 18:10:36 +01001809 free(err_msg);
1810}
1811
Willy Tarreau76871a42022-03-08 16:01:40 +01001812/* call the various keyword dump functions based on the comma-delimited list of
1813 * classes in kwd_dump.
1814 */
1815static void dump_registered_keywords(void)
1816{
1817 char *end;
1818 int all __maybe_unused = 0;
1819
1820 for (; kwd_dump && *kwd_dump; kwd_dump = end) {
1821 end = strchr(kwd_dump, ',');
1822 if (end)
1823 *(end++) = 0;
1824
1825 if (strcmp(kwd_dump, "help") == 0) {
1826 printf("# List of supported keyword classes:\n");
1827 printf("all: list all keywords\n");
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001828 printf("acl: ACL keywords\n");
Willy Tarreauca1acd62022-03-29 15:02:44 +02001829 printf("cfg: configuration keywords\n");
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001830 printf("cli: CLI keywords\n");
Willy Tarreau29d799d2022-03-29 16:59:49 +02001831 printf("cnv: sample converter keywords\n");
Willy Tarreau3b65e142022-03-29 15:03:09 +02001832 printf("flt: filter names\n");
Willy Tarreauf78813f2022-03-29 16:51:29 +02001833 printf("smp: sample fetch functions\n");
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001834 printf("svc: service names\n");
Willy Tarreau76871a42022-03-08 16:01:40 +01001835 continue;
1836 }
1837 else if (strcmp(kwd_dump, "all") == 0) {
1838 all = 1;
1839 }
Willy Tarreauca1acd62022-03-29 15:02:44 +02001840
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001841 if (all || strcmp(kwd_dump, "acl") == 0) {
1842 printf("# List of registered ACL keywords:\n");
1843 acl_dump_kwd();
1844 }
1845
Willy Tarreauca1acd62022-03-29 15:02:44 +02001846 if (all || strcmp(kwd_dump, "cfg") == 0) {
1847 printf("# List of registered configuration keywords:\n");
1848 cfg_dump_registered_keywords();
1849 }
Willy Tarreau3b65e142022-03-29 15:03:09 +02001850
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001851 if (all || strcmp(kwd_dump, "cli") == 0) {
1852 printf("# List of registered CLI keywords:\n");
1853 cli_list_keywords();
1854 }
1855
Willy Tarreau29d799d2022-03-29 16:59:49 +02001856 if (all || strcmp(kwd_dump, "cnv") == 0) {
1857 printf("# List of registered sample converter functions:\n");
1858 smp_dump_conv_kw();
1859 }
1860
Willy Tarreau3b65e142022-03-29 15:03:09 +02001861 if (all || strcmp(kwd_dump, "flt") == 0) {
1862 printf("# List of registered filter names:\n");
1863 flt_dump_kws(NULL);
1864 }
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001865
Willy Tarreauf78813f2022-03-29 16:51:29 +02001866 if (all || strcmp(kwd_dump, "smp") == 0) {
1867 printf("# List of registered sample fetch functions:\n");
1868 smp_dump_fetch_kw();
1869 }
1870
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001871 if (all || strcmp(kwd_dump, "svc") == 0) {
1872 printf("# List of registered service names:\n");
1873 list_services(NULL);
1874 }
Willy Tarreau76871a42022-03-08 16:01:40 +01001875 }
1876}
1877
Willy Tarreau392524d2022-02-17 18:10:36 +01001878/*
1879 * This function initializes all the necessary variables. It only returns
1880 * if everything is OK. If something fails, it exits.
1881 */
1882static void init(int argc, char **argv)
1883{
1884 char *progname = global.log_tag.area;
1885 int err_code = 0;
1886 struct wordlist *wl;
1887 struct proxy *px;
1888 struct post_check_fct *pcf;
1889 int ideal_maxconn;
1890
1891 if (!init_trash_buffers(1)) {
1892 ha_alert("failed to initialize trash buffers.\n");
1893 exit(1);
1894 }
1895
1896 if (init_acl() != 0)
1897 exit(1);
1898
1899 /* Initialise lua. */
1900 hlua_init();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901
Christopher Faulete3a5e352017-10-24 13:53:54 +02001902 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001903 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Willy Tarreau76871a42022-03-08 16:01:40 +01001904 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905
William Lallemand944e6192018-11-21 15:48:31 +01001906 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001907 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001908 global.mode |= MODE_MWORKER_WAIT;
1909 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001910 }
1911
Willy Tarreau26146192021-07-21 10:01:36 +02001912 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1913 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001914 atexit_flag = 1;
1915 atexit(reexec_on_failure);
1916 }
1917
Willy Tarreau576132e2011-09-10 19:26:56 +02001918 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001919 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001920 exit(1);
1921 }
1922
Amaury Denoyelle11124302021-06-04 18:22:08 +02001923 usermsgs_clr("config");
1924
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001925 if (global.mode & MODE_CHECK_CONDITION) {
1926 int result;
1927
1928 uint32_t err;
1929 const char *errptr;
1930 char *errmsg = NULL;
1931
1932 char *args[MAX_LINE_ARGS+1];
1933 int arg = sizeof(args) / sizeof(*args);
1934 size_t outlen = strlen(check_condition) + 1;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001935 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001936
1937 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001938 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001939 &errptr);
1940
1941 if (err & PARSE_ERR_QUOTE) {
1942 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1943 exit(2);
1944 }
1945
1946 if (err & PARSE_ERR_HEX) {
1947 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1948 exit(2);
1949 }
1950
1951 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1952 ha_alert("Error in condition: Line too long.\n");
1953 exit(2);
1954 }
1955
Willy Tarreauc8194c32021-07-16 16:38:58 +02001956 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001957 ha_alert("Error in condition: Too many words.\n");
1958 exit(2);
1959 }
1960
1961 if (err) {
1962 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1963 exit(2);
1964 }
1965
Willy Tarreauc8194c32021-07-16 16:38:58 +02001966 /* remerge all words into a single expression */
1967 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1968 ;
1969
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001970 result = cfg_eval_condition(args, &errmsg, &errptr);
1971
1972 if (result < 0) {
1973 if (errmsg)
1974 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1975
1976 exit(2);
1977 }
1978
1979 exit(result ? 0 : 1);
1980 }
1981
William Lallemand944e6192018-11-21 15:48:31 +01001982 /* in wait mode, we don't try to read the configuration files */
1983 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001984 char *env_cfgfiles = NULL;
1985 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001986
William Lallemand944e6192018-11-21 15:48:31 +01001987 /* handle cfgfiles that are actually directories */
1988 cfgfiles_expand_directories();
1989
1990 if (LIST_ISEMPTY(&cfg_cfgfiles))
1991 usage(progname);
1992
1993
1994 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1995 int ret;
1996
Christopher Faulet4e366822021-01-12 18:57:38 +01001997 if (env_err == 0) {
1998 if (!memprintf(&env_cfgfiles, "%s%s%s",
1999 (env_cfgfiles ? env_cfgfiles : ""),
2000 (env_cfgfiles ? ";" : ""), wl->s))
2001 env_err = 1;
2002 }
William Lallemand7b302d82019-05-20 11:15:37 +02002003
William Lallemand944e6192018-11-21 15:48:31 +01002004 ret = readcfgfile(wl->s);
2005 if (ret == -1) {
2006 ha_alert("Could not open configuration file %s : %s\n",
2007 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01002008 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002009 exit(1);
2010 }
2011 if (ret & (ERR_ABORT|ERR_FATAL))
2012 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
2013 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01002014 if (err_code & ERR_ABORT) {
2015 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002016 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01002017 }
Willy Tarreauc4382422009-12-06 13:10:44 +01002018 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02002019
William Lallemand944e6192018-11-21 15:48:31 +01002020 /* do not try to resolve arguments nor to spot inconsistencies when
2021 * the configuration contains fatal errors caused by files not found
2022 * or failed memory allocations.
2023 */
2024 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2025 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01002026 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002027 exit(1);
2028 }
Christopher Faulet4e366822021-01-12 18:57:38 +01002029 if (env_err) {
2030 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
2031 exit(1);
2032 }
2033 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
2034 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02002035
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02002036 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002037 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01002038 struct mworker_proc *tmproc;
2039
William Lallemand482f9a92019-04-12 16:15:00 +02002040 setenv("HAPROXY_MWORKER", "1", 1);
2041
William Lallemand16dd1b32018-11-19 18:46:18 +01002042 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
2043
William Lallemand56be0e02022-01-28 21:11:41 +01002044 tmproc = mworker_proc_new();
William Lallemand16dd1b32018-11-19 18:46:18 +01002045 if (!tmproc) {
2046 ha_alert("Cannot allocate process structures.\n");
2047 exit(EXIT_FAILURE);
2048 }
William Lallemand8f7069a2019-04-12 16:09:23 +02002049 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01002050 tmproc->pid = pid;
2051 tmproc->timestamp = start_date.tv_sec;
William Lallemand16dd1b32018-11-19 18:46:18 +01002052 proc_self = tmproc;
2053
Willy Tarreau2b718102021-04-21 07:32:39 +02002054 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01002055 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002056
William Lallemand56be0e02022-01-28 21:11:41 +01002057 tmproc = mworker_proc_new();
Willy Tarreau6185a032021-06-15 08:02:06 +02002058 if (!tmproc) {
2059 ha_alert("Cannot allocate process structures.\n");
2060 exit(EXIT_FAILURE);
2061 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002062 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02002063
Willy Tarreau6185a032021-06-15 08:02:06 +02002064 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
2065 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02002066 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002067
2068 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01002069 }
2070 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
2071 struct wordlist *it, *c;
2072
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02002073 /* get the info of the children in the env */
2074 if (mworker_env_to_proc_list() < 0) {
2075 exit(EXIT_FAILURE);
2076 }
William Lallemande7361152018-10-26 14:47:36 +02002077
William Lallemand550db6d2018-11-06 17:37:12 +01002078 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02002079
William Lallemand550db6d2018-11-06 17:37:12 +01002080 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02002081 ha_alert("Can't create the master's CLI.\n");
2082 exit(EXIT_FAILURE);
2083 }
William Lallemande7361152018-10-26 14:47:36 +02002084
William Lallemand550db6d2018-11-06 17:37:12 +01002085 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
2086
2087 if (mworker_cli_proxy_new_listener(c->s) < 0) {
2088 ha_alert("Can't create the master's CLI.\n");
2089 exit(EXIT_FAILURE);
2090 }
Willy Tarreau2b718102021-04-21 07:32:39 +02002091 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01002092 free(c->s);
2093 free(c);
2094 }
2095 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002096 }
2097
Eric Salama5ba83352021-03-16 15:11:17 +01002098 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2099 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2100 }
2101
Christopher Faulet27c8d202021-10-13 09:50:53 +02002102 /* destroy unreferenced defaults proxies */
2103 proxy_destroy_all_unref_defaults();
2104
Willy Tarreaue90904d2021-02-12 14:08:31 +01002105
Willy Tarreaubb925012009-07-23 13:36:36 +02002106 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002107 for (px = proxies_list; px; px = px->next) {
2108 struct server *srv;
2109 struct post_proxy_check_fct *ppcf;
2110 struct post_server_check_fct *pscf;
2111
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002112 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002113 continue;
2114
Christopher Fauletc1692962019-08-12 09:51:07 +02002115 list_for_each_entry(pscf, &post_server_check_list, list) {
2116 for (srv = px->srv; srv; srv = srv->next)
2117 err_code |= pscf->fct(srv);
2118 }
2119 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2120 err_code |= ppcf->fct(px);
2121 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002122 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002123 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002124 exit(1);
2125 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002126
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002127 err_code |= pattern_finalize_config();
2128 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2129 ha_alert("Failed to finalize pattern config.\n");
2130 exit(1);
2131 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002132
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002133 if (global.rlimit_memmax_all)
2134 global.rlimit_memmax = global.rlimit_memmax_all;
2135
Willy Tarreaue5733232019-05-22 19:24:06 +02002136#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002137 err_code |= netns_init();
2138 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002139 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002140 exit(1);
2141 }
2142#endif
2143
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002144 /* Apply server states */
2145 apply_server_state();
2146
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002147 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002148 srv_compute_all_admin_states(px);
2149
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002150 /* Apply servers' configured address */
2151 err_code |= srv_init_addr();
2152 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002153 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002154 exit(1);
2155 }
2156
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002157 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2158 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2159 exit(1);
2160 }
2161
Willy Tarreau654726d2021-12-28 15:43:11 +01002162#if defined(HA_HAVE_DUMP_LIBS)
2163 if (global.mode & MODE_DUMP_LIBS) {
2164 qfprintf(stdout, "List of loaded object files:\n");
2165 chunk_reset(&trash);
2166 if (dump_libs(&trash, 0))
2167 printf("%s", trash.area);
2168 }
2169#endif
2170
Willy Tarreau76871a42022-03-08 16:01:40 +01002171 if (global.mode & MODE_DUMP_KWD)
2172 dump_registered_keywords();
2173
Willy Tarreaubaaee002006-06-26 02:48:02 +02002174 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002175 struct peers *pr;
2176 struct proxy *px;
2177
Willy Tarreaubebd2122020-04-15 16:06:11 +02002178 if (warned & WARN_ANY)
2179 qfprintf(stdout, "Warnings were found.\n");
2180
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002181 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002182 if (pr->peers_fe)
2183 break;
2184
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002185 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002186 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002187 break;
2188
Emeric Brunbc5c8212021-08-13 09:32:50 +02002189 if (!px) {
2190 /* We may only have log-forward section */
2191 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002192 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002193 break;
2194 }
2195
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002196 if (pr || px) {
2197 /* At least one peer or one listener has been found */
2198 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002199 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002200 }
2201 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2202 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002203 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002204
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002205 if (global.mode & MODE_DIAG) {
2206 cfg_run_diagnostics();
2207 }
2208
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002209 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002210 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002211
Willy Tarreaue6945732016-12-21 19:57:00 +01002212 list_for_each_entry(pcf, &post_check_list, list) {
2213 err_code |= pcf->fct();
2214 if (err_code & (ERR_ABORT|ERR_FATAL))
2215 exit(1);
2216 }
2217
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 if (cfg_maxconn > 0)
2219 global.maxconn = cfg_maxconn;
2220
Willy Tarreau4975d142021-03-13 11:00:33 +01002221 if (global.cli_fe)
2222 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002223
2224 if (cfg_peers) {
2225 /* peers also need to bypass global maxconn */
2226 struct peers *p = cfg_peers;
2227
2228 for (p = cfg_peers; p; p = p->next)
2229 if (p->peers_fe)
2230 global.maxsock += p->peers_fe->maxconn;
2231 }
2232
Willy Tarreaud0256482015-01-15 21:45:22 +01002233 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002234 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2235 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2236 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2237 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002238 *
2239 * If memmax is set, then it depends on which values are set. If
2240 * maxsslconn is set, we use memmax to determine how many cleartext
2241 * connections may be added, and set maxconn to the sum of the two.
2242 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2243 * the remaining amount of memory between memmax and the cleartext
2244 * connections. If neither are set, then it is considered that all
2245 * connections are SSL-capable, and maxconn is computed based on this,
2246 * then maxsslconn accordingly. We need to know if SSL is used on the
2247 * frontends, backends, or both, because when it's used on both sides,
2248 * we need twice the value for maxsslconn, but we only count the
2249 * handshake once since it is not performed on the two sides at the
2250 * same time (frontend-side is terminated before backend-side begins).
2251 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002252 * ssl_handshake_cost during its initialization. In any case, if
2253 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2254 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002255 */
Willy Tarreauac350932019-03-01 15:43:14 +01002256 ideal_maxconn = compute_ideal_maxconn();
2257
Willy Tarreaud0256482015-01-15 21:45:22 +01002258 if (!global.rlimit_memmax) {
2259 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002260 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002261 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2262 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2263 }
2264 }
2265#ifdef USE_OPENSSL
2266 else if (!global.maxconn && !global.maxsslconn &&
2267 (global.ssl_used_frontend || global.ssl_used_backend)) {
2268 /* memmax is set, compute everything automatically. Here we want
2269 * to ensure that all SSL connections will be served. We take
2270 * care of the number of sides where SSL is used, and consider
2271 * the worst case : SSL used on both sides and doing a handshake
2272 * simultaneously. Note that we can't have more than maxconn
2273 * handshakes at a time by definition, so for the worst case of
2274 * two SSL conns per connection, we count a single handshake.
2275 */
2276 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2277 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002278 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002279
2280 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2281 mem -= global.maxzlibmem;
2282 mem = mem * MEM_USABLE_RATIO;
2283
Willy Tarreau304e17e2020-03-10 17:54:54 +01002284 /* Principle: we test once to set maxconn according to the free
2285 * memory. If it results in values the system rejects, we try a
2286 * second time by respecting rlim_fd_max. If it fails again, we
2287 * go back to the initial value and will let the final code
2288 * dealing with rlimit report the error. That's up to 3 attempts.
2289 */
2290 do {
2291 global.maxconn = mem /
2292 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2293 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2294 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002295
Willy Tarreau304e17e2020-03-10 17:54:54 +01002296 if (retried == 1)
2297 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2298 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002299#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002300 if (global.maxconn > SYSTEM_MAXCONN)
2301 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002302#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002303 global.maxsslconn = sides * global.maxconn;
2304
2305 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2306 break;
2307 } while (retried++ < 2);
2308
Willy Tarreaud0256482015-01-15 21:45:22 +01002309 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2310 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2311 global.maxconn, global.maxsslconn);
2312 }
2313 else if (!global.maxsslconn &&
2314 (global.ssl_used_frontend || global.ssl_used_backend)) {
2315 /* memmax and maxconn are known, compute maxsslconn automatically.
2316 * maxsslconn being forced, we don't know how many of it will be
2317 * on each side if both sides are being used. The worst case is
2318 * when all connections use only one SSL instance because
2319 * handshakes may be on two sides at the same time.
2320 */
2321 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2322 int64_t mem = global.rlimit_memmax * 1048576ULL;
2323 int64_t sslmem;
2324
2325 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2326 mem -= global.maxzlibmem;
2327 mem = mem * MEM_USABLE_RATIO;
2328
Willy Tarreau87b09662015-04-03 00:22:06 +02002329 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002330 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2331 global.maxsslconn = round_2dig(global.maxsslconn);
2332
2333 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002334 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2335 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2336 "without SSL is %d, but %d was found and SSL is in use.\n",
2337 global.rlimit_memmax,
2338 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2339 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002340 exit(1);
2341 }
2342
2343 if (global.maxsslconn > sides * global.maxconn)
2344 global.maxsslconn = sides * global.maxconn;
2345
2346 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2347 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2348 }
2349#endif
2350 else if (!global.maxconn) {
2351 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2352 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2353 int64_t mem = global.rlimit_memmax * 1048576ULL;
2354 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002355 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002356
2357 if (global.ssl_used_frontend || global.ssl_used_backend)
2358 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2359
2360 mem -= global.maxzlibmem;
2361 mem = mem * MEM_USABLE_RATIO;
2362
2363 clearmem = mem;
2364 if (sides)
2365 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2366
Willy Tarreau304e17e2020-03-10 17:54:54 +01002367 /* Principle: we test once to set maxconn according to the free
2368 * memory. If it results in values the system rejects, we try a
2369 * second time by respecting rlim_fd_max. If it fails again, we
2370 * go back to the initial value and will let the final code
2371 * dealing with rlimit report the error. That's up to 3 attempts.
2372 */
2373 do {
2374 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2375 if (retried == 1)
2376 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2377 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002378#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002379 if (global.maxconn > SYSTEM_MAXCONN)
2380 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002381#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002382
Willy Tarreau304e17e2020-03-10 17:54:54 +01002383 if (clearmem <= 0 || !global.maxconn) {
2384 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2385 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2386 "is %d, but %d was found.\n",
2387 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002388 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002389 global.maxsslconn);
2390 exit(1);
2391 }
2392
2393 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2394 break;
2395 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002396
2397 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2398 if (sides && global.maxsslconn > sides * global.maxconn) {
2399 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2400 "to be limited to %d. Better reduce global.maxsslconn to get more "
2401 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2402 }
2403 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2404 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002405 }
2406
Willy Tarreaua409f302020-03-10 17:08:53 +01002407 global.maxsock = compute_ideal_maxsock(global.maxconn);
2408 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002409 if (!global.maxpipes)
2410 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411
Olivier Houchard88698d92019-04-16 19:07:22 +02002412 /* update connection pool thresholds */
2413 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2414 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2415
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002416 proxy_adjust_all_maxconn();
2417
Willy Tarreau1db37712007-06-03 17:16:49 +02002418 if (global.tune.maxpollevents <= 0)
2419 global.tune.maxpollevents = MAX_POLL_EVENTS;
2420
Willy Tarreau060a7612021-03-10 11:06:26 +01002421 if (global.tune.runqueue_depth <= 0) {
2422 /* tests on various thread counts from 1 to 64 have shown an
2423 * optimal queue depth following roughly 1/sqrt(threads).
2424 */
2425 int s = my_flsl(global.nbthread);
2426 s += (global.nbthread / s); // roughly twice the sqrt.
2427 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2428 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002429
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002430 if (global.tune.recv_enough == 0)
2431 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2432
Willy Tarreau27a674e2009-08-17 07:23:33 +02002433 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2434 global.tune.maxrewrite = global.tune.bufsize / 2;
2435
Amaury Denoyelle11124302021-06-04 18:22:08 +02002436 usermsgs_clr(NULL);
2437
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2439 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002440 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002441 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2442 }
2443
William Lallemand095ba4c2017-06-01 17:38:50 +02002444 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002445 /* command line daemon mode inhibits foreground and debug modes mode */
2446 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002447 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002448 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002449
2450 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002451
William Lallemand095ba4c2017-06-01 17:38:50 +02002452 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002453 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002454 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 }
2456
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002457 if (global.nbthread < 1)
2458 global.nbthread = 1;
2459
Christopher Faulet3ef26392017-08-29 16:46:57 +02002460 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002461 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002462 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002463 exit(1);
2464 }
2465
Christopher Faulet96d44832017-11-14 22:02:30 +01002466 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002467 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002468 exit(1);
2469 }
2470
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002471 /*
2472 * Note: we could register external pollers here.
2473 * Built-in pollers have been registered before main().
2474 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002475
Willy Tarreau43b78992009-01-25 15:42:27 +01002476 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002477 disable_poller("kqueue");
2478
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002479 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2480 disable_poller("evports");
2481
Willy Tarreau43b78992009-01-25 15:42:27 +01002482 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002483 disable_poller("epoll");
2484
Willy Tarreau43b78992009-01-25 15:42:27 +01002485 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002486 disable_poller("poll");
2487
Willy Tarreau43b78992009-01-25 15:42:27 +01002488 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002489 disable_poller("select");
2490
2491 /* Note: we could disable any poller by name here */
2492
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002493 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002494 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002495 fprintf(stderr, "\n");
2496 list_filters(stderr);
2497 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002498
Willy Tarreau4f60f162007-04-08 16:39:58 +02002499 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002500 ha_alert("No polling mechanism available.\n"
2501 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2502 " is too low on this platform to support maxconn and the number of listeners\n"
2503 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2504 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2505 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2506 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2507 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2508 " check build settings using 'haproxy -vv'.\n\n",
2509 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002510 exit(1);
2511 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002512 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2513 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002514 }
2515
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002516 if (!global.node)
2517 global.node = strdup(hostname);
2518
Willy Tarreau02b092f2020-10-07 18:36:54 +02002519 /* stop disabled proxies */
2520 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002521 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002522 stop_proxy(px);
2523 }
2524
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002525 if (!hlua_post_init())
2526 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002527}
2528
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002529void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002530{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002531 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002532 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002533 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002534 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002535 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002536 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002537 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002538 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002539 struct per_thread_init_fct *tif, *tifb;
2540 struct per_thread_deinit_fct *tdf, *tdfb;
2541 struct per_thread_alloc_fct *taf, *tafb;
2542 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002543 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002544 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002545 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002546 int cur_fd;
2547
2548 /* At this point the listeners state is weird:
2549 * - most listeners are still bound and referenced in their protocol
2550 * - some might be zombies that are not in their proto anymore, but
2551 * still appear in their proxy's listeners with a valid FD.
2552 * - some might be stopped and still appear in their proxy as FD #-1
2553 * - among all of them, some might be inherited hence shared and we're
2554 * not allowed to pause them or whatever, we must just close them.
2555 * - finally some are not listeners (pipes, logs, stdout, etc) and
2556 * must be left intact.
2557 *
2558 * The safe way to proceed is to unbind (and close) whatever is not yet
2559 * unbound so that no more receiver/listener remains alive. Then close
2560 * remaining listener FDs, which correspond to zombie listeners (those
2561 * belonging to disabled proxies that were in another process).
2562 * objt_listener() would be cleaner here but not converted yet.
2563 */
2564 protocol_unbind_all();
2565
2566 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002567 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002568 continue;
2569
Willy Tarreaua74cb382020-10-15 21:29:49 +02002570 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002571 struct listener *l = fdtab[cur_fd].owner;
2572
2573 BUG_ON(l->state != LI_INIT);
2574 unbind_listener(l);
2575 }
2576 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002577
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002578 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002580 /* build a list of unique uri_auths */
2581 if (!ua)
2582 ua = p->uri_auth;
2583 else {
2584 /* check if p->uri_auth is unique */
2585 for (uap = ua; uap; uap=uap->next)
2586 if (uap == p->uri_auth)
2587 break;
2588
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002589 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002590 /* add it, if it is */
2591 p->uri_auth->next = ua;
2592 ua = p->uri_auth;
2593 }
William Lallemand0f99e342011-10-12 17:50:54 +02002594 }
2595
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002596 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002597 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002598 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002600
Christopher Faulet27c8d202021-10-13 09:50:53 +02002601 /* destroy all referenced defaults proxies */
2602 proxy_destroy_all_unref_defaults();
2603
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002604 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002605 struct stat_scope *scope, *scopep;
2606
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002607 uap = ua;
2608 ua = ua->next;
2609
Willy Tarreaua534fea2008-08-03 12:19:50 +02002610 free(uap->uri_prefix);
2611 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002612 free(uap->node);
2613 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002614
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002615 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002616 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002617
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002618 scope = uap->scope;
2619 while (scope) {
2620 scopep = scope;
2621 scope = scope->next;
2622
2623 free(scopep->px_id);
2624 free(scopep);
2625 }
2626
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002627 free(uap);
2628 }
2629
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002630 userlist_free(userlist);
2631
David Carlier834cb2e2015-09-25 12:02:25 +01002632 cfg_unregister_sections();
2633
Christopher Faulet0132d062017-07-26 15:33:35 +02002634 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002635
Willy Tarreau05554e62016-12-21 20:46:26 +01002636 list_for_each_entry(pdf, &post_deinit_list, list)
2637 pdf->fct();
2638
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002639 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002640 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002641 ha_free(&global.chroot);
2642 ha_free(&global.pidfile);
2643 ha_free(&global.node);
2644 ha_free(&global.desc);
2645 ha_free(&oldpids);
2646 ha_free(&old_argv);
2647 ha_free(&localpeer);
2648 ha_free(&global.server_state_base);
2649 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002650 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002651 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002652
William Lallemand0f99e342011-10-12 17:50:54 +02002653 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002654 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002655 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002656 free(log);
2657 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002658 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002659 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002660 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002661 free(wl);
2662 }
2663
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002664 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2665 if (bol->must_free)
2666 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002667 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002668 free(bol);
2669 }
2670
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002671 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002672 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002673 free(pxdf);
2674 }
2675
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002676 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002677 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002678 free(pdf);
2679 }
2680
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002681 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002682 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002683 free(srvdf);
2684 }
2685
Tim Duesterhusfc854942020-09-10 19:46:42 +02002686 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002687 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002688 free(pcf);
2689 }
2690
Tim Duesterhus34bef072020-07-04 11:49:50 +02002691 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002692 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002693 free(pscf);
2694 }
2695
Tim Duesterhus53508d62020-09-10 19:46:40 +02002696 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002697 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002698 free(ppcf);
2699 }
2700
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002701 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002702 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002703 free(tif);
2704 }
2705
2706 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002707 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002708 free(tdf);
2709 }
2710
2711 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002712 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002713 free(taf);
2714 }
2715
2716 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002717 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002718 free(tff);
2719 }
2720
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002721 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002722 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002723 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002724} /* end deinit() */
2725
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002726__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002727{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002728 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002729 deinit();
2730 exit(status);
2731}
William Lallemand72160322018-11-06 17:37:16 +01002732
Willy Tarreau918ff602011-07-25 16:33:49 +02002733/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002734void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002735{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002736 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002737
Willy Tarreau55542642021-10-08 09:33:24 +02002738 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002739 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002740 wake_expired_tasks();
2741
William Lallemand1aab50b2018-06-07 09:46:01 +02002742 /* check if we caught some signals and process them in the
2743 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002744 if (signal_queue_len && tid == 0) {
2745 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002746 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002747 }
2748
2749 /* Process a few tasks */
2750 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002751
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002752 /* also stop if we failed to cleanly stop all tasks */
2753 if (killed > 1)
2754 break;
2755
Willy Tarreau10146c92015-04-13 20:44:19 +02002756 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002757 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002758 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002759 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002760 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002761 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2762 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002763 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002764 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002765 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002766 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002767 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002768 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002769
Willy Tarreau4f46a352020-03-23 09:27:28 +01002770 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002771 int i;
2772
2773 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002774 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002775 if (!(stopping_thread_mask & tid_bit)) {
2776 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2777 wake = 1;
2778 }
2779
Willy Tarreau1db42732021-04-06 11:44:07 +02002780 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002781 /* notify all threads that stopping was just set */
2782 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002783 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002784 wake_thread(i);
2785 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002786 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002787
2788 /* stop when there's nothing left to do */
2789 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002790 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2791 /* wake all threads waiting on jobs==0 */
2792 for (i = 0; i < global.nbthread; i++)
2793 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2794 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002795 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002796 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002797 }
2798
Willy Tarreauc49ba522019-12-11 08:12:23 +01002799 /* If we have to sleep, measure how long */
2800 next = wake ? TICK_ETERNITY : next_timer_expiry();
2801
Willy Tarreau58b458d2008-06-29 22:40:23 +02002802 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002803 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002804
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002805 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002806 }
2807}
2808
Christopher Faulet1d17c102017-08-29 15:38:48 +02002809static void *run_thread_poll_loop(void *data)
2810{
Willy Tarreau082b6282019-05-22 14:42:12 +02002811 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002812 struct per_thread_init_fct *ptif;
2813 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002814 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002815 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002816 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2817 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002818
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002819 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002820 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002821 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002822
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002823 /* Now, initialize one thread init at a time. This is better since
2824 * some init code is a bit tricky and may release global resources
2825 * after reallocating them locally. This will also ensure there is
2826 * no race on file descriptors allocation.
2827 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002828#ifdef USE_THREAD
2829 pthread_mutex_lock(&init_mutex);
2830#endif
2831 /* The first thread must set the number of threads left */
2832 if (!init_left)
2833 init_left = global.nbthread;
2834 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002835
Willy Tarreau55542642021-10-08 09:33:24 +02002836 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002837
Willy Tarreau082b6282019-05-22 14:42:12 +02002838 /* per-thread alloc calls performed here are not allowed to snoop on
2839 * other threads, so they are free to initialize at their own rhythm
2840 * as long as they act as if they were alone. None of them may rely
2841 * on resources initialized by the other ones.
2842 */
2843 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2844 if (!ptaf->fct()) {
2845 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002846#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002847 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002848#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002849 exit(1);
2850 }
2851 }
2852
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002853 /* per-thread init calls performed here are not allowed to snoop on
2854 * other threads, so they are free to initialize at their own rhythm
2855 * as long as they act as if they were alone.
2856 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002857 list_for_each_entry(ptif, &per_thread_init_list, list) {
2858 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002859 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002860#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002861 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002862#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002863 exit(1);
2864 }
2865 }
2866
Willy Tarreau71092822019-06-10 09:51:04 +02002867 /* enabling protocols will result in fd_insert() calls to be performed,
2868 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002869 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002870 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002871 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002872 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002873
Willy Tarreau34a150c2019-06-11 09:16:41 +02002874#ifdef USE_THREAD
2875 pthread_cond_broadcast(&init_cond);
2876 pthread_mutex_unlock(&init_mutex);
2877
2878 /* now wait for other threads to finish starting */
2879 pthread_mutex_lock(&init_mutex);
2880 while (init_left)
2881 pthread_cond_wait(&init_cond, &init_mutex);
2882 pthread_mutex_unlock(&init_mutex);
2883#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002884
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002885#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2886 /* Let's refrain from using setuid executables. This way the impact of
2887 * an eventual vulnerability in a library remains limited. It may
2888 * impact external checks but who cares about them anyway ? In the
2889 * worst case it's possible to disable the option. Obviously we do this
2890 * in workers only. We can't hard-fail on this one as it really is
2891 * implementation dependent though we're interested in feedback, hence
2892 * the warning.
2893 */
2894 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2895 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002896 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 +01002897 ha_warning("Failed to disable setuid, please report to developers with detailed "
2898 "information about your operating system. You can silence this warning "
2899 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2900 }
2901 }
2902#endif
2903
Willy Tarreaud96f1122019-12-03 07:07:36 +01002904#if defined(RLIMIT_NPROC)
2905 /* all threads have started, it's now time to prevent any new thread
2906 * or process from starting. Obviously we do this in workers only. We
2907 * can't hard-fail on this one as it really is implementation dependent
2908 * though we're interested in feedback, hence the warning.
2909 */
2910 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2911 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2912 static int warn_fail;
2913
Willy Tarreau18515722021-04-06 11:57:41 +02002914 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002915 ha_warning("Failed to disable forks, please report to developers with detailed "
2916 "information about your operating system. You can silence this warning "
2917 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2918 }
2919 }
2920#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002921 run_poll_loop();
2922
2923 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2924 ptdf->fct();
2925
Willy Tarreau082b6282019-05-22 14:42:12 +02002926 list_for_each_entry(ptff, &per_thread_free_list, list)
2927 ptff->fct();
2928
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002929#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002930 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002931 if (tid > 0)
2932 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002933#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002934 return NULL;
2935}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002936
William Dauchyf9af9d72019-11-17 15:47:16 +01002937/* set uid/gid depending on global settings */
2938static void set_identity(const char *program_name)
2939{
2940 if (global.gid) {
2941 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2942 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2943 " without 'uid'/'user' is generally useless.\n", program_name);
2944
2945 if (setgid(global.gid) == -1) {
2946 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2947 protocol_unbind_all();
2948 exit(1);
2949 }
2950 }
2951
2952 if (global.uid && setuid(global.uid) == -1) {
2953 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2954 protocol_unbind_all();
2955 exit(1);
2956 }
2957}
2958
Willy Tarreaubaaee002006-06-26 02:48:02 +02002959int main(int argc, char **argv)
2960{
2961 int err, retry;
2962 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002963 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02002964 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2965
2966 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2967 if (intovf + 0x7FFFFFFF >= intovf) {
2968 fprintf(stderr,
2969 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2970 "The source code was miscompiled by the compiler, which usually indicates that\n"
2971 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2972 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2973 "and INSTALL files to decide on the best way to pass your local build options.\n"
2974 "\nBuild options :"
2975#ifdef BUILD_TARGET
2976 "\n TARGET = " BUILD_TARGET
2977#endif
2978#ifdef BUILD_CPU
2979 "\n CPU = " BUILD_CPU
2980#endif
2981#ifdef BUILD_CC
2982 "\n CC = " BUILD_CC
2983#endif
2984#ifdef BUILD_CFLAGS
2985 "\n CFLAGS = " BUILD_CFLAGS
2986#endif
2987#ifdef BUILD_OPTIONS
2988 "\n OPTIONS = " BUILD_OPTIONS
2989#endif
2990#ifdef BUILD_DEBUG
2991 "\n DEBUG = " BUILD_DEBUG
2992#endif
2993 "\n\n");
2994 return 1;
2995 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002996
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002997 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002998
Willy Tarreaubf696402019-03-01 10:09:28 +01002999 /* take a copy of initial limits before we possibly change them */
3000 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02003001
3002 if (limit.rlim_max == RLIM_INFINITY)
3003 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01003004 rlim_fd_cur_at_boot = limit.rlim_cur;
3005 rlim_fd_max_at_boot = limit.rlim_max;
3006
Willy Tarreau5794fb02018-11-25 18:43:29 +01003007 /* process all initcalls in order of potential dependency */
3008 RUN_INITCALLS(STG_PREPARE);
3009 RUN_INITCALLS(STG_LOCK);
Willy Tarreau3ebe4d92022-02-18 14:51:49 +01003010 RUN_INITCALLS(STG_REGISTER);
Willy Tarreau34527d52022-02-17 17:45:58 +01003011
3012 /* now's time to initialize early boot variables */
3013 init_early(argc, argv);
3014
Willy Tarreau18f96d02022-02-23 17:25:00 +01003015 /* handles argument parsing */
3016 init_args(argc, argv);
3017
Willy Tarreau5794fb02018-11-25 18:43:29 +01003018 RUN_INITCALLS(STG_ALLOC);
3019 RUN_INITCALLS(STG_POOL);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003020 RUN_INITCALLS(STG_INIT);
3021
Willy Tarreau34527d52022-02-17 17:45:58 +01003022 /* this is the late init where the config is parsed */
Emeric Bruncf20bf12010-10-22 16:06:11 +02003023 init(argc, argv);
Willy Tarreau34527d52022-02-17 17:45:58 +01003024
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003025 signal_register_fct(SIGQUIT, dump, SIGQUIT);
3026 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
3027 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02003028 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029
Willy Tarreaue437c442010-03-17 18:02:46 +01003030 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
3031 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
3032 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003034 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003035
Willy Tarreaudc23a922011-02-16 11:10:36 +01003036 /* ulimits */
3037 if (!global.rlimit_nofile)
3038 global.rlimit_nofile = global.maxsock;
3039
3040 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01003041 limit.rlim_cur = global.rlimit_nofile;
3042 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
3043
Willy Tarreaudc23a922011-02-16 11:10:36 +01003044 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02003045 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003046 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3047 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
3048 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003049 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003050 }
3051 else {
3052 /* try to set it to the max possible at least */
3053 limit.rlim_cur = limit.rlim_max;
3054 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
3055 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02003056
William Dauchya5194602020-03-28 19:29:58 +01003057 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003058 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
3059 global.rlimit_nofile = limit.rlim_cur;
3060 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01003061 }
3062 }
3063
3064 if (global.rlimit_memmax) {
3065 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01003066 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01003067#ifdef RLIMIT_AS
3068 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003069 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3070 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3071 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003072 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003073 }
3074 else
William Dauchya5194602020-03-28 19:29:58 +01003075 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003076 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003077 }
3078#else
3079 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003080 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3081 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3082 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003083 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003084 }
3085 else
William Dauchya5194602020-03-28 19:29:58 +01003086 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003087 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003088 }
3089#endif
3090 }
3091
William Lallemandf82afbb2022-01-07 18:19:42 +01003092 /* Try to get the listeners FD from the previous process using
3093 * _getsocks on the stat socket, it must never been done in wait mode
3094 * and check mode
3095 */
3096 if (old_unixsocket &&
3097 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK|MODE_CHECK_CONDITION))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003098 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003099 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003100 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003101 if (!(global.mode & MODE_MWORKER))
3102 exit(1);
3103 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003104 }
3105 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003106
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 /* We will loop at most 100 times with 10 ms delay each time.
3108 * That's at most 1 second. We only send a signal to old pids
3109 * if we cannot grab at least one port.
3110 */
3111 retry = MAX_START_RETRIES;
3112 err = ERR_NONE;
3113 while (retry >= 0) {
3114 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003115 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003116 /* exit the loop on no error or fatal error */
3117 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003119 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 break;
3121
3122 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3123 * listening sockets. So on those platforms, it would be wiser to
3124 * simply send SIGUSR1, which will not be undoable.
3125 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003126 if (tell_old_pids(SIGTTOU) == 0) {
3127 /* no need to wait if we can't contact old pids */
3128 retry = 0;
3129 continue;
3130 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 /* give some time to old processes to stop listening */
3132 w.tv_sec = 0;
3133 w.tv_usec = 10*1000;
3134 select(0, NULL, NULL, NULL, &w);
3135 retry--;
3136 }
3137
Willy Tarreaue91bff22020-09-02 11:11:43 +02003138 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003139 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003140 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003141 if (retry != MAX_START_RETRIES && nb_oldpids) {
3142 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 exit(1);
3146 }
3147
William Lallemand944e6192018-11-21 15:48:31 +01003148 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003149 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 /* Note: we don't have to send anything to the old pids because we
3151 * never stopped them. */
3152 exit(1);
3153 }
3154
Willy Tarreaue91bff22020-09-02 11:11:43 +02003155 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003156 * the previous process gave us, we don't need them anymore
3157 */
Willy Tarreaub5101162022-01-28 18:28:18 +01003158 sock_drop_unused_old_sockets();
Willy Tarreaudd815982007-10-16 12:25:14 +02003159
Willy Tarreaubaaee002006-06-26 02:48:02 +02003160 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003161 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3162 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163
Willy Tarreaubaaee002006-06-26 02:48:02 +02003164 /* MODE_QUIET can inhibit alerts and warnings below this line */
3165
PiBa-NL149a81a2017-12-25 21:03:31 +01003166 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3167 /* either stdin/out/err are already closed or should stay as they are. */
3168 if ((global.mode & MODE_DAEMON)) {
3169 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3170 global.mode &= ~MODE_VERBOSE;
3171 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3172 }
3173 } else {
3174 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3175 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003176 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 }
3179
3180 /* open log & pid files before the chroot */
William Lallemand7b820a62022-02-14 09:02:14 +01003181 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) &&
3182 !(global.mode & MODE_MWORKER_WAIT) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003183 unlink(global.pidfile);
3184 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3185 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003186 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 if (nb_oldpids)
3188 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003189 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 exit(1);
3191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 }
3193
Willy Tarreaub38651a2007-03-24 17:24:39 +01003194 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003195 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3196 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003197 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003198 exit(1);
3199 }
3200
Jackie Tapia749f74c2020-07-22 18:59:40 -05003201 /* If the user is not root, we'll still let them try the configuration
3202 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003203 */
3204 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003205 ha_warning("[%s.main()] Some options which require full privileges"
3206 " might not work well.\n"
3207 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003208
William Lallemand095ba4c2017-06-01 17:38:50 +02003209 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3210
3211 /* chroot if needed */
3212 if (global.chroot != NULL) {
3213 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003214 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003215 if (nb_oldpids)
3216 tell_old_pids(SIGTTIN);
3217 protocol_unbind_all();
3218 exit(1);
3219 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003220 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003221 }
3222
William Lallemand944e6192018-11-21 15:48:31 +01003223 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003224 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003225
William Lallemand27edc4b2019-05-07 17:49:33 +02003226 /* send a SIGTERM to workers who have a too high reloads number */
3227 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3228 mworker_kill_max_reloads(SIGTERM);
3229
Willy Tarreaubaaee002006-06-26 02:48:02 +02003230 /* Note that any error at this stage will be fatal because we will not
3231 * be able to restart the old pids.
3232 */
3233
William Dauchyf9af9d72019-11-17 15:47:16 +01003234 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3235 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003236
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 /* check ulimits */
3238 limit.rlim_cur = limit.rlim_max = 0;
3239 getrlimit(RLIMIT_NOFILE, &limit);
3240 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003241 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3242 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3243 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3244 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3245 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003246 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003247 }
3248 else
3249 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003250 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003251 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3252 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 }
3254
William Lallemand944e6192018-11-21 15:48:31 +01003255 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003257 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003258 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003259
William Lallemand095ba4c2017-06-01 17:38:50 +02003260 /*
3261 * if daemon + mworker: must fork here to let a master
3262 * process live in background before forking children
3263 */
William Lallemand73b85e72017-06-01 17:38:51 +02003264
3265 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3266 && (global.mode & MODE_MWORKER)
3267 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003268 ret = fork();
3269 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003270 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003271 protocol_unbind_all();
3272 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003273 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003274 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003275 } else /* change the process group ID in the child (master process) */
3276 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003277 }
William Lallemande20b6a62017-06-01 17:38:55 +02003278
William Lallemande20b6a62017-06-01 17:38:55 +02003279
William Lallemanddeed7802017-11-06 11:00:04 +01003280 /* if in master-worker mode, write the PID of the father */
3281 if (global.mode & MODE_MWORKER) {
3282 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003283 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003284 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003285 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003286 }
3287
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003289 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003290 if (global.mode & MODE_MWORKER)
3291 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003292
3293 ret = fork();
3294 if (ret < 0) {
3295 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3296 protocol_unbind_all();
3297 exit(1); /* there has been an error */
3298 }
3299 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003300 /* This one must not be exported, it's internal! */
3301 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003302 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003303 }
3304 else { /* parent here */
3305 in_parent = 1;
3306
William Lallemand944e6192018-11-21 15:48:31 +01003307 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3308 char pidstr[100];
3309 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003310 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003311 }
3312 if (global.mode & MODE_MWORKER) {
3313 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003314
William Lallemand5d71a6b2021-11-09 15:25:31 +01003315 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003316 /* find the right mworker_proc */
3317 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003318 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003319 child->timestamp = now.tv_sec;
3320 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003321 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003322 break;
3323 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003324 }
3325 }
William Lallemand944e6192018-11-21 15:48:31 +01003326 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003327
William Lallemand944e6192018-11-21 15:48:31 +01003328 } else {
3329 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003330 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003331 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003332
3333#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003334 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 +02003335
David CARLIERdf91cbd2022-01-06 18:53:50 +00003336#if defined(CPUSET_USE_CPUSET) || defined(__DragonFly__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003337 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003338 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
David CARLIERdf91cbd2022-01-06 18:53:50 +00003339#elif defined(__FreeBSD__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003340 struct hap_cpuset *set = &cpu_map.proc;
David CARLIERdf91cbd2022-01-06 18:53:50 +00003341 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003342#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003343 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003344#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003346 if (pidfd >= 0) {
3347 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3348 close(pidfd);
3349 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003350
3351 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003352 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353
Willy Tarreaud67ff342021-06-15 07:58:09 +02003354 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003355 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003356 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003357
3358 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3359 (global.mode & MODE_DAEMON)) {
3360 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003361 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3362 stdio_quiet(-1);
3363
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003364 global.mode &= ~MODE_VERBOSE;
3365 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003366 }
3367
William Lallemandfab0fdc2021-11-09 18:01:22 +01003368 if (global.mode & MODE_MWORKER_WAIT) {
3369 /* only the wait mode handles the master CLI */
3370 mworker_loop();
3371 } else {
3372
3373 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand836bda22021-11-09 18:16:47 +01003374 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003375 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003376 mworker_reexec_waitmode();
3377 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003378 /* should never get there */
3379 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003380 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003381#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003382 ssl_free_dh();
3383#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003384 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003385 }
3386
William Lallemandcb11fd22017-06-01 17:38:52 +02003387 /* child must never use the atexit function */
3388 atexit_flag = 0;
3389
William Lallemandbc193052018-09-11 10:06:26 +02003390 /* close useless master sockets */
3391 if (global.mode & MODE_MWORKER) {
3392 struct mworker_proc *child, *it;
3393 master = 0;
3394
William Lallemand309dc9a2018-10-26 14:47:45 +02003395 mworker_cli_proxy_stop();
3396
William Lallemandbc193052018-09-11 10:06:26 +02003397 /* free proc struct of other processes */
3398 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003399 /* close the FD of the master side for all
3400 * workers, we don't need to close the worker
3401 * side of other workers since it's done with
3402 * the bind_proc */
William Lallemand7e018782022-01-28 21:56:24 +01003403 if (child->ipc_fd[0] >= 0) {
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003404 close(child->ipc_fd[0]);
William Lallemand7e018782022-01-28 21:56:24 +01003405 child->ipc_fd[0] = -1;
3406 }
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003407 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003408 child->reloads == 0) {
3409 /* keep this struct if this is our pid */
3410 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003411 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003412 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003413 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003414 mworker_free_child(child);
3415 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003416 }
3417 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003418
William Lallemande1340412017-12-28 16:09:36 +01003419 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3420 devnullfd = open("/dev/null", O_RDWR, 0);
3421 if (devnullfd < 0) {
3422 ha_alert("Cannot open /dev/null\n");
3423 exit(EXIT_FAILURE);
3424 }
3425 }
3426
William Lallemand095ba4c2017-06-01 17:38:50 +02003427 /* Must chroot and setgid/setuid in the children */
3428 /* chroot if needed */
3429 if (global.chroot != NULL) {
3430 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003431 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003432 if (nb_oldpids)
3433 tell_old_pids(SIGTTIN);
3434 protocol_unbind_all();
3435 exit(1);
3436 }
3437 }
3438
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003439 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003440 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003441
William Lallemand7f80eb22017-05-26 18:19:55 +02003442 /* pass through every cli socket, and check if it's bound to
3443 * the current process and if it exposes listeners sockets.
3444 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3445 * */
3446
Willy Tarreau4975d142021-03-13 11:00:33 +01003447 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003448 struct bind_conf *bind_conf;
3449
Willy Tarreau4975d142021-03-13 11:00:33 +01003450 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003451 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003452 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3453 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003454 }
3455 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003456 }
3457
William Lallemand2e8fad92018-11-13 16:18:23 +01003458 /*
3459 * This is only done in daemon mode because we might want the
3460 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3461 * we should now close the 3 first FDs to ensure that we can
3462 * detach from the TTY. We MUST NOT do it in other cases since
3463 * it would have already be done, and 0-2 would have been
3464 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003466 if ((global.mode & MODE_DAEMON) &&
3467 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003468 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003469 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003470 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003471 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3472 }
3473 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003474 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3475 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003476 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003477 }
3478
William Dauchye039f262019-11-17 15:47:15 +01003479 /* try our best to re-enable core dumps depending on system capabilities.
3480 * What is addressed here :
3481 * - remove file size limits
3482 * - remove core size limits
3483 * - mark the process dumpable again if it lost it due to user/group
3484 */
3485 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3486 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3487
3488#if defined(RLIMIT_FSIZE)
3489 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3490 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3491 ha_alert("[%s.main()] Failed to set the raise the maximum "
3492 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003493 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003494 }
3495 else
3496 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003497 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003498 }
3499#endif
3500
3501#if defined(RLIMIT_CORE)
3502 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3503 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3504 ha_alert("[%s.main()] Failed to set the raise the core "
3505 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003506 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003507 }
3508 else
3509 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003510 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003511 }
3512#endif
3513
3514#if defined(USE_PRCTL)
3515 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3516 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3517 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003518#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003519 {
3520 int traceable = PROC_TRACE_CTL_ENABLE;
3521 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3522 ha_warning("[%s.main()] Failed to set the traceable flag, "
3523 "no core will be dumped.\n", argv[0]);
3524 }
William Dauchye039f262019-11-17 15:47:15 +01003525#endif
3526 }
3527
Christopher Faulete3a5e352017-10-24 13:53:54 +02003528 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003529 reset_usermsgs_ctx();
3530
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003531 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003532 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003533
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003534 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003535 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003536
3537 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003538 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003539
3540 /* wait for all threads to terminate */
3541 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003542
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003543 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544}
3545
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546/*
3547 * Local variables:
3548 * c-indent-level: 8
3549 * c-basic-offset: 8
3550 * End:
3551 */