blob: d4658f6055f427ffdd563a9ae5827b3b585aa42e [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * HA-Proxy : High Availability-enabled HTTP/TCP proxy
Willy Tarreau9233c212021-01-08 21:19:40 +01003 * Copyright 2000-2021 Willy Tarreau <willy@haproxy.org>.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
Ilya Shipitsin46a030c2020-07-05 16:36:08 +050010 * Please refer to RFC7230 - RFC7235 information about HTTP protocol, and
11 * RFC6265 for information about cookies usage. More generally, the IETF HTTP
Willy Tarreaubaaee002006-06-26 02:48:02 +020012 * Working Group's web site should be consulted for protocol related changes :
13 *
14 * http://ftp.ics.uci.edu/pub/ietf/http/
15 *
16 * Pending bugs (may be not fixed because never reproduced) :
17 * - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
18 * the proxy to terminate (no core) if the client breaks the connection during
19 * the response. Seen on 1.1.8pre4, but never reproduced. May not be related to
20 * the snprintf() bug since requests were simple (GET / HTTP/1.0), but may be
21 * related to missing setsid() (fixed in 1.1.15)
22 * - a proxy with an invalid config will prevent the startup even if disabled.
23 *
24 * ChangeLog has moved to the CHANGELOG file.
25 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020026 */
27
David Carlier7ece0962015-12-08 21:43:09 +000028#define _GNU_SOURCE
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include <ctype.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020034#include <dirent.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020035#include <sys/stat.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <sys/time.h>
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <netinet/tcp.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <signal.h>
46#include <stdarg.h>
47#include <sys/resource.h>
Tim Duesterhusdfad6a42020-04-18 16:02:47 +020048#include <sys/utsname.h>
Marc-Antoine Perennou992709b2013-02-12 10:53:52 +010049#include <sys/wait.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <time.h>
51#include <syslog.h>
Michael Schererab012dd2013-01-12 18:35:19 +010052#include <grp.h>
Willy Tarreaufc6c0322012-11-16 16:12:27 +010053#ifdef USE_CPU_AFFINITY
Willy Tarreaufc6c0322012-11-16 16:12:27 +010054#include <sched.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000055#if defined(__FreeBSD__) || defined(__DragonFly__)
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020056#include <sys/param.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000057#ifdef __FreeBSD__
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020058#include <sys/cpuset.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000059#endif
David Carlier6d5c8412017-11-29 11:02:32 +000060#include <pthread_np.h>
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020061#endif
David Carlier5e4c8e22019-09-13 05:12:58 +010062#ifdef __APPLE__
63#include <mach/mach_types.h>
64#include <mach/thread_act.h>
65#include <mach/thread_policy.h>
66#endif
Willy Tarreaufc6c0322012-11-16 16:12:27 +010067#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020068
Willy Tarreau636848a2019-04-15 19:38:50 +020069#if defined(USE_PRCTL)
70#include <sys/prctl.h>
71#endif
72
Willy Tarreaubaaee002006-06-26 02:48:02 +020073#ifdef DEBUG_FULL
74#include <assert.h>
75#endif
Tim Duesterhusd6942c82017-11-20 15:58:35 +010076#if defined(USE_SYSTEMD)
77#include <systemd/sd-daemon.h>
78#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020079
Willy Tarreau6c3a6812020-03-06 18:57:15 +010080#include <import/sha1.h>
81
Willy Tarreaub2551052020-06-09 09:07:15 +020082#include <haproxy/acl.h>
83#include <haproxy/activity.h>
84#include <haproxy/api.h>
85#include <haproxy/arg.h>
86#include <haproxy/auth.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020087#include <haproxy/base64.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020088#include <haproxy/capture-t.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020089#include <haproxy/cfgparse.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020090#include <haproxy/chunk.h>
Willy Tarreau83487a82020-06-04 20:19:54 +020091#include <haproxy/cli.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020092#include <haproxy/connection.h>
Willy Tarreaueb92deb2020-06-04 10:53:16 +020093#include <haproxy/dns.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +020094#include <haproxy/dynbuf.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020095#include <haproxy/errors.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020096#include <haproxy/fd.h>
Willy Tarreauc7babd82020-06-04 21:29:29 +020097#include <haproxy/filters.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020098#include <haproxy/global.h>
Willy Tarreau86416052020-06-04 09:20:54 +020099#include <haproxy/hlua.h>
Willy Tarreauc761f842020-06-04 11:40:28 +0200100#include <haproxy/http_rules.h>
Willy Tarreau853b2972020-05-27 18:01:47 +0200101#include <haproxy/list.h>
Willy Tarreau213e9902020-06-04 14:58:24 +0200102#include <haproxy/listener.h>
Willy Tarreauaeed4a82020-06-04 22:01:04 +0200103#include <haproxy/log.h>
Willy Tarreaub5abe5b2020-06-04 14:07:37 +0200104#include <haproxy/mworker.h>
Willy Tarreau7a00efb2020-06-02 17:02:59 +0200105#include <haproxy/namespace.h>
Willy Tarreau6131d6a2020-06-02 16:48:09 +0200106#include <haproxy/net_helper.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +0200107#include <haproxy/openssl-compat.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200108#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200109#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200110#include <haproxy/pool.h>
111#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200112#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200113#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200114#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200115#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200116#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200117#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200118#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200119#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200120#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200121#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200122#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200123#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200124#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200125#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200126#include <haproxy/time.h>
127#include <haproxy/tools.h>
128#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200129#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200130#include <haproxy/version.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200131
Willy Tarreaubaaee002006-06-26 02:48:02 +0200132
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100133/* array of init calls for older platforms */
134DECLARE_INIT_STAGES;
135
Willy Tarreau477ecd82010-01-03 21:12:30 +0100136/* list of config files */
137static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200138int pid; /* current process id */
Willy Tarreau28156642007-11-26 16:13:36 +0100139int relative_pid = 1; /* process id starting at 1 */
Willy Tarreau387bd4f2017-11-10 19:08:14 +0100140unsigned long pid_bit = 1; /* bit corresponding to the process id */
Willy Tarreaua38a7172019-02-02 17:11:28 +0100141unsigned long all_proc_mask = 1; /* mask of all processes */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200142
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100143volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100144volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100145
Willy Tarreaubaaee002006-06-26 02:48:02 +0200146/* global options */
147struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100148 .hard_stop_after = TICK_ETERNITY,
Willy Tarreau247a13a2012-11-15 17:38:15 +0100149 .nbproc = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100150 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200151 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200152 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
William Lallemand9d5f5482012-11-07 16:12:57 +0100153 .maxzlibmem = 0,
William Lallemandd85f9172012-11-09 17:05:39 +0100154 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100155 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200156 .unix_bind = {
157 .ux = {
158 .uid = -1,
159 .gid = -1,
160 .mode = 0,
161 }
162 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200163 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100164 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100165 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100166 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100167 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200168 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200169 .pool_low_ratio = 20,
170 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200171 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200172#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100173 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200174#endif
William Lallemandf3747832012-11-09 12:33:10 +0100175 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100176#ifdef DEFAULT_IDLE_TIMER
177 .idle_timer = DEFAULT_IDLE_TIMER,
178#else
179 .idle_timer = 1000, /* 1 second */
180#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200181 },
Emeric Brun76d88952012-10-05 15:47:31 +0200182#ifdef USE_OPENSSL
183#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200184 .maxsslconn = DEFAULT_MAXSSLCONN,
185#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200186#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187 /* others NULL OK */
188};
189
190/*********************************************************************/
191
192int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100193int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200194int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100195int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100196int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100197int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500199/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200 * or kill. We will send them a signal every 10 ms until we can bind to all
201 * our ports. With 200 retries, that's about 2 seconds.
202 */
203#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204static int *oldpids = NULL;
205static int oldpids_sig; /* use USR1 or TERM */
206
Olivier Houchardf73629d2017-04-05 22:33:04 +0200207/* Path to the unix socket we use to retrieve listener sockets from the old process */
208static const char *old_unixsocket;
209
William Lallemand85b0bd92017-06-01 17:38:53 +0200210static char *cur_unixsocket = NULL;
211
William Lallemandcb11fd22017-06-01 17:38:52 +0200212int atexit_flag = 0;
213
Willy Tarreaubb545b42010-08-25 12:58:59 +0200214int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215const int zero = 0;
216const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200217const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100219char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200220char *localpeer = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221
William Lallemand00417412020-06-05 14:08:41 +0200222static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200223
William Lallemandbc193052018-09-11 10:06:26 +0200224struct list proc_list = LIST_HEAD_INIT(proc_list);
225
226int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100227unsigned int rlim_fd_cur_at_boot = 0;
228unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200229
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100230/* per-boot randomness */
231unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
232
William Lallemand16dd1b32018-11-19 18:46:18 +0100233struct mworker_proc *proc_self = NULL;
William Lallemandbc193052018-09-11 10:06:26 +0200234
William Lallemandb3f2be32018-09-11 10:06:18 +0200235static void *run_thread_poll_loop(void *data);
236
Willy Tarreauff055502014-04-28 22:27:06 +0200237/* bitfield of a few warnings to emit just once (WARN_*) */
238unsigned int warned = 0;
239
William Lallemande7361152018-10-26 14:47:36 +0200240/* master CLI configuration (-S flag) */
241struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100242
243/* These are strings to be reported in the output of "haproxy -vv". They may
244 * either be constants (in which case must_free must be zero) or dynamically
245 * allocated strings to pass to free() on exit, and in this case must_free
246 * must be non-zero.
247 */
248struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
249struct build_opts_str {
250 struct list list;
251 const char *str;
252 int must_free;
253};
254
Willy Tarreaue6945732016-12-21 19:57:00 +0100255/* These functions are called just after the point where the program exits
256 * after a config validity check, so they are generally suited for resource
257 * allocation and slow initializations that should be skipped during basic
258 * config checks. The functions must return 0 on success, or a combination
259 * of ERR_* flags (ERR_WARN, ERR_ABORT, ERR_FATAL, ...). The 2 latter cause
260 * and immediate exit, so the function must have emitted any useful error.
261 */
262struct list post_check_list = LIST_HEAD_INIT(post_check_list);
263struct post_check_fct {
264 struct list list;
265 int (*fct)();
266};
267
Christopher Fauletc1692962019-08-12 09:51:07 +0200268/* These functions are called for each proxy just after the config validity
269 * check. The functions must return 0 on success, or a combination of ERR_*
270 * flags (ERR_WARN, ERR_ABORT, ERR_FATAL, ...). The 2 latter cause and immediate
271 * exit, so the function must have emitted any useful error.
272 */
273struct list post_proxy_check_list = LIST_HEAD_INIT(post_proxy_check_list);
274struct post_proxy_check_fct {
275 struct list list;
276 int (*fct)(struct proxy *);
277};
278
279/* These functions are called for each server just after the config validity
280 * check. The functions must return 0 on success, or a combination of ERR_*
281 * flags (ERR_WARN, ERR_ABORT, ERR_FATAL, ...). The 2 latter cause and immediate
282 * exit, so the function must have emitted any useful error.
283 */
284struct list post_server_check_list = LIST_HEAD_INIT(post_server_check_list);
285struct post_server_check_fct {
286 struct list list;
287 int (*fct)(struct server *);
288};
289
Willy Tarreau082b6282019-05-22 14:42:12 +0200290/* These functions are called for each thread just after the thread creation
291 * and before running the init functions. They should be used to do per-thread
292 * (re-)allocations that are needed by subsequent functoins. They must return 0
293 * if an error occurred. */
294struct list per_thread_alloc_list = LIST_HEAD_INIT(per_thread_alloc_list);
295struct per_thread_alloc_fct {
Willy Tarreau05554e62016-12-21 20:46:26 +0100296 struct list list;
Willy Tarreau082b6282019-05-22 14:42:12 +0200297 int (*fct)();
Willy Tarreau05554e62016-12-21 20:46:26 +0100298};
299
Christopher Faulet415f6112017-07-25 16:52:58 +0200300/* These functions are called for each thread just after the thread creation
301 * and before running the scheduler. They should be used to do per-thread
302 * initializations. They must return 0 if an error occurred. */
303struct list per_thread_init_list = LIST_HEAD_INIT(per_thread_init_list);
304struct per_thread_init_fct {
305 struct list list;
306 int (*fct)();
307};
308
Willy Tarreau082b6282019-05-22 14:42:12 +0200309/* These functions are called when freeing the global sections at the end of
310 * deinit, after everything is stopped. They don't return anything. They should
311 * not release shared resources that are possibly used by other deinit
312 * functions, only close/release what is private. Use the per_thread_free_list
313 * to release shared resources.
314 */
315struct list post_deinit_list = LIST_HEAD_INIT(post_deinit_list);
316struct post_deinit_fct {
317 struct list list;
318 void (*fct)();
319};
320
Christopher Faulet3ea5cbe2019-07-31 08:44:12 +0200321/* These functions are called when freeing a proxy during the deinit, after
322 * everything isg stopped. They don't return anything. They should not release
323 * the proxy itself or any shared resources that are possibly used by other
324 * deinit functions, only close/release what is private.
325 */
326struct list proxy_deinit_list = LIST_HEAD_INIT(proxy_deinit_list);
327struct proxy_deinit_fct {
328 struct list list;
329 void (*fct)(struct proxy *);
330};
331
332/* These functions are called when freeing a server during the deinit, after
333 * everything isg stopped. They don't return anything. They should not release
334 * the proxy itself or any shared resources that are possibly used by other
335 * deinit functions, only close/release what is private.
336 */
337struct list server_deinit_list = LIST_HEAD_INIT(server_deinit_list);
338struct server_deinit_fct {
339 struct list list;
340 void (*fct)(struct server *);
341};
342
Willy Tarreau082b6282019-05-22 14:42:12 +0200343/* These functions are called when freeing the global sections at the end of
344 * deinit, after the thread deinit functions, to release unneeded memory
345 * allocations. They don't return anything, and they work in best effort mode
346 * as their sole goal is to make valgrind mostly happy.
347 */
348struct list per_thread_free_list = LIST_HEAD_INIT(per_thread_free_list);
349struct per_thread_free_fct {
350 struct list list;
Christopher Fauletbbda99b2020-11-06 15:19:19 +0100351 void (*fct)();
Willy Tarreau082b6282019-05-22 14:42:12 +0200352};
353
Christopher Faulet415f6112017-07-25 16:52:58 +0200354/* These functions are called for each thread just after the scheduler loop and
355 * before exiting the thread. They don't return anything and, as for post-deinit
356 * functions, they work in best effort mode as their sole goal is to make
357 * valgrind mostly happy. */
358struct list per_thread_deinit_list = LIST_HEAD_INIT(per_thread_deinit_list);
359struct per_thread_deinit_fct {
360 struct list list;
361 void (*fct)();
362};
363
Willy Tarreaubaaee002006-06-26 02:48:02 +0200364/*********************************************************************/
365/* general purpose functions ***************************************/
366/*********************************************************************/
367
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100368/* used to register some build option strings at boot. Set must_free to
369 * non-zero if the string must be freed upon exit.
370 */
371void hap_register_build_opts(const char *str, int must_free)
372{
373 struct build_opts_str *b;
374
375 b = calloc(1, sizeof(*b));
376 if (!b) {
377 fprintf(stderr, "out of memory\n");
378 exit(1);
379 }
380 b->str = str;
381 b->must_free = must_free;
382 LIST_ADDQ(&build_opts_list, &b->list);
383}
384
Willy Tarreaue6945732016-12-21 19:57:00 +0100385/* used to register some initialization functions to call after the checks. */
386void hap_register_post_check(int (*fct)())
387{
388 struct post_check_fct *b;
389
390 b = calloc(1, sizeof(*b));
391 if (!b) {
392 fprintf(stderr, "out of memory\n");
393 exit(1);
394 }
395 b->fct = fct;
396 LIST_ADDQ(&post_check_list, &b->list);
397}
398
Christopher Fauletc1692962019-08-12 09:51:07 +0200399/* used to register some initialization functions to call for each proxy after
400 * the checks.
401 */
402void hap_register_post_proxy_check(int (*fct)(struct proxy *))
403{
404 struct post_proxy_check_fct *b;
405
406 b = calloc(1, sizeof(*b));
407 if (!b) {
408 fprintf(stderr, "out of memory\n");
409 exit(1);
410 }
411 b->fct = fct;
412 LIST_ADDQ(&post_proxy_check_list, &b->list);
413}
414
415/* used to register some initialization functions to call for each server after
416 * the checks.
417 */
418void hap_register_post_server_check(int (*fct)(struct server *))
419{
420 struct post_server_check_fct *b;
421
422 b = calloc(1, sizeof(*b));
423 if (!b) {
424 fprintf(stderr, "out of memory\n");
425 exit(1);
426 }
427 b->fct = fct;
428 LIST_ADDQ(&post_server_check_list, &b->list);
429}
430
Willy Tarreau05554e62016-12-21 20:46:26 +0100431/* used to register some de-initialization functions to call after everything
432 * has stopped.
433 */
434void hap_register_post_deinit(void (*fct)())
435{
436 struct post_deinit_fct *b;
437
438 b = calloc(1, sizeof(*b));
439 if (!b) {
440 fprintf(stderr, "out of memory\n");
441 exit(1);
442 }
443 b->fct = fct;
444 LIST_ADDQ(&post_deinit_list, &b->list);
445}
446
Christopher Faulet3ea5cbe2019-07-31 08:44:12 +0200447/* used to register some per proxy de-initialization functions to call after
448 * everything has stopped.
449 */
450void hap_register_proxy_deinit(void (*fct)(struct proxy *))
451{
452 struct proxy_deinit_fct *b;
453
454 b = calloc(1, sizeof(*b));
455 if (!b) {
456 fprintf(stderr, "out of memory\n");
457 exit(1);
458 }
459 b->fct = fct;
460 LIST_ADDQ(&proxy_deinit_list, &b->list);
461}
462
463
464/* used to register some per server de-initialization functions to call after
465 * everything has stopped.
466 */
467void hap_register_server_deinit(void (*fct)(struct server *))
468{
469 struct server_deinit_fct *b;
470
471 b = calloc(1, sizeof(*b));
472 if (!b) {
473 fprintf(stderr, "out of memory\n");
474 exit(1);
475 }
476 b->fct = fct;
477 LIST_ADDQ(&server_deinit_list, &b->list);
478}
479
Willy Tarreau082b6282019-05-22 14:42:12 +0200480/* used to register some allocation functions to call for each thread. */
481void hap_register_per_thread_alloc(int (*fct)())
482{
483 struct per_thread_alloc_fct *b;
484
485 b = calloc(1, sizeof(*b));
486 if (!b) {
487 fprintf(stderr, "out of memory\n");
488 exit(1);
489 }
490 b->fct = fct;
491 LIST_ADDQ(&per_thread_alloc_list, &b->list);
492}
493
Christopher Faulet415f6112017-07-25 16:52:58 +0200494/* used to register some initialization functions to call for each thread. */
495void hap_register_per_thread_init(int (*fct)())
496{
497 struct per_thread_init_fct *b;
498
499 b = calloc(1, sizeof(*b));
500 if (!b) {
501 fprintf(stderr, "out of memory\n");
502 exit(1);
503 }
504 b->fct = fct;
505 LIST_ADDQ(&per_thread_init_list, &b->list);
506}
507
508/* used to register some de-initialization functions to call for each thread. */
509void hap_register_per_thread_deinit(void (*fct)())
510{
511 struct per_thread_deinit_fct *b;
512
513 b = calloc(1, sizeof(*b));
514 if (!b) {
515 fprintf(stderr, "out of memory\n");
516 exit(1);
517 }
518 b->fct = fct;
519 LIST_ADDQ(&per_thread_deinit_list, &b->list);
520}
521
Willy Tarreau082b6282019-05-22 14:42:12 +0200522/* used to register some free functions to call for each thread. */
Christopher Fauletbbda99b2020-11-06 15:19:19 +0100523void hap_register_per_thread_free(void (*fct)())
Willy Tarreau082b6282019-05-22 14:42:12 +0200524{
525 struct per_thread_free_fct *b;
526
527 b = calloc(1, sizeof(*b));
528 if (!b) {
529 fprintf(stderr, "out of memory\n");
530 exit(1);
531 }
532 b->fct = fct;
533 LIST_ADDQ(&per_thread_free_list, &b->list);
534}
535
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100536static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200537{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200538 struct utsname utsname;
539
Willy Tarreau08dd2022019-11-21 18:07:30 +0100540 printf("HA-Proxy version %s %s - https://haproxy.org/\n"
541 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100542
543 if (strlen(PRODUCT_URL_BUGS) > 0) {
544 char base_version[20];
545 int dots = 0;
546 char *del;
547
548 /* only retrieve the base version without distro-specific extensions */
549 for (del = haproxy_version; *del; del++) {
550 if (*del == '.')
551 dots++;
552 else if (*del < '0' || *del > '9')
553 break;
554 }
555
556 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
557 if (dots < 2)
558 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
559 else
560 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
561 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200562
563 if (uname(&utsname) == 0) {
564 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566}
567
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100568static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100569{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100570 struct build_opts_str *item;
571
Willy Tarreau7b066db2007-12-02 11:28:59 +0100572 printf("Build options :"
573#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100574 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100575#endif
576#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100577 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100578#endif
579#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100580 "\n CC = " BUILD_CC
581#endif
582#ifdef BUILD_CFLAGS
583 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100584#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100585#ifdef BUILD_OPTIONS
586 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100587#endif
Tim Duesterhusc21f2272020-11-21 18:07:59 +0100588#ifdef BUILD_DEBUG
589 "\n DEBUG = " BUILD_DEBUG
590#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100591#ifdef BUILD_FEATURES
592 "\n\nFeature list : " BUILD_FEATURES
593#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200594 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100595 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200596 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100597 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200598
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100599 list_for_each_entry(item, &build_opts_list, list) {
600 puts(item->str);
601 }
602
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100603 putchar('\n');
604
Willy Tarreaube5b6852009-10-03 18:57:08 +0200605 list_pollers(stdout);
606 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200607 list_mux_proto(stdout);
608 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100609 list_services(stdout);
610 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100611 list_filters(stdout);
612 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100613}
614
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615/*
616 * This function prints the command line usage and exits
617 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100618static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200619{
620 display_version();
621 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200622 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200623 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200624 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100625 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreau6e064432012-05-08 15:40:42 +0200627 " -dM[<byte>] poisons memory with <byte> (defaults to 0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200629 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200630 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100631#if defined(USE_SYSTEMD)
632 " -Ws master-worker mode with systemd notify support.\n"
633#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200634 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200635 " -c check mode : only check config files and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100636 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637 " -m limits the usable amount of memory (in MB)\n"
638 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200639 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200640 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200641#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 " -de disables epoll() usage even when available\n"
643#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200644#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200645 " -dk disables kqueue() usage even when available\n"
646#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200647#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000648 " -dv disables event ports usage even when available\n"
649#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200650#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200651 " -dp disables poll() usage even when available\n"
652#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200653#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100654 " -dS disables splice usage (broken on old kernels)\n"
655#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200656#if defined(USE_GETADDRINFO)
657 " -dG disables getaddrinfo() usage\n"
658#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000659#if defined(SO_REUSEPORT)
660 " -dR disables SO_REUSEPORT usage\n"
661#endif
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100662 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100663 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200664 " -dW fails if any warning is emitted\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200665 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200666 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200667 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200668 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100669 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 exit(1);
671}
672
673
674
675/*********************************************************************/
676/* more specific functions ***************************************/
677/*********************************************************************/
678
William Lallemand73b85e72017-06-01 17:38:51 +0200679/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
680 * pids the signal was correctly delivered to.
681 */
William Lallemande25473c2019-04-01 11:29:56 +0200682int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200683{
684 int p;
685 int ret = 0;
686 for (p = 0; p < nb_oldpids; p++)
687 if (kill(oldpids[p], sig) == 0)
688 ret++;
689 return ret;
690}
691
William Lallemand75ea0a02017-11-15 19:02:58 +0100692/*
William Lallemand73b85e72017-06-01 17:38:51 +0200693 * remove a pid forom the olpid array and decrease nb_oldpids
694 * return 1 pid was found otherwise return 0
695 */
696
697int delete_oldpid(int pid)
698{
699 int i;
700
701 for (i = 0; i < nb_oldpids; i++) {
702 if (oldpids[i] == pid) {
703 oldpids[i] = oldpids[nb_oldpids - 1];
704 oldpids[nb_oldpids - 1] = 0;
705 nb_oldpids--;
706 return 1;
707 }
708 }
709 return 0;
710}
711
William Lallemand85b0bd92017-06-01 17:38:53 +0200712
713static void get_cur_unixsocket()
714{
715 /* if -x was used, try to update the stat socket if not available anymore */
716 if (global.stats_fe) {
717 struct bind_conf *bind_conf;
718
719 /* pass through all stats socket */
720 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
721 struct listener *l;
722
723 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
724
Willy Tarreau37159062020-08-27 07:48:42 +0200725 if (l->rx.addr.ss_family == AF_UNIX &&
William Lallemand85b0bd92017-06-01 17:38:53 +0200726 (bind_conf->level & ACCESS_FD_LISTENERS)) {
727 const struct sockaddr_un *un;
728
Willy Tarreau37159062020-08-27 07:48:42 +0200729 un = (struct sockaddr_un *)&l->rx.addr;
William Lallemand85b0bd92017-06-01 17:38:53 +0200730 /* priority to old_unixsocket */
731 if (!cur_unixsocket) {
732 cur_unixsocket = strdup(un->sun_path);
733 } else {
734 if (old_unixsocket && !strcmp(un->sun_path, old_unixsocket)) {
735 free(cur_unixsocket);
736 cur_unixsocket = strdup(old_unixsocket);
737 return;
738 }
739 }
740 }
741 }
742 }
743 }
744 if (!cur_unixsocket && old_unixsocket)
745 cur_unixsocket = strdup(old_unixsocket);
746}
747
William Lallemand73b85e72017-06-01 17:38:51 +0200748/*
749 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800750 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200751 */
William Lallemanda57b7e32018-12-14 21:11:31 +0100752void mworker_reload()
William Lallemand73b85e72017-06-01 17:38:51 +0200753{
William Lallemand00417412020-06-05 14:08:41 +0200754 char **next_argv = NULL;
755 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200756 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200757 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200758 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100759 struct rlimit limit;
William Lallemand7c756a82018-11-26 11:53:40 +0100760 struct per_thread_deinit_fct *ptdf;
William Lallemand73b85e72017-06-01 17:38:51 +0200761
762 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100763#if defined(USE_SYSTEMD)
764 if (global.tune.options & GTUNE_USE_SYSTEMD)
765 sd_notify(0, "RELOADING=1");
766#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200767 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
768
William Lallemandbc193052018-09-11 10:06:26 +0200769 mworker_proc_list_to_env(); /* put the children description in the env */
770
William Lallemand7c756a82018-11-26 11:53:40 +0100771 /* during the reload we must ensure that every FDs that can't be
772 * reuse (ie those that are not referenced in the proc_list)
773 * are closed or they will leak. */
774
775 /* close the listeners FD */
776 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200777
778 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
779 /* close the poller FD and the thread waker pipe FD */
780 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
781 ptdf->fct();
782 if (fdtab)
783 deinit_pollers();
784 }
Willy Tarreau5db847a2019-05-09 14:13:35 +0200785#if defined(USE_OPENSSL) && (HA_OPENSSL_VERSION_NUMBER >= 0x10101000L)
William Lallemand5fdb5b32019-10-15 14:04:08 +0200786 /* close random device FDs */
787 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100788#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100789
Willy Tarreau8dca1952019-03-01 10:21:55 +0100790 /* restore the initial FD limits */
791 limit.rlim_cur = rlim_fd_cur_at_boot;
792 limit.rlim_max = rlim_fd_max_at_boot;
793 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
794 getrlimit(RLIMIT_NOFILE, &limit);
795 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
796 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
797 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
798 }
799
William Lallemand73b85e72017-06-01 17:38:51 +0200800 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200801 while (old_argv[old_argc])
802 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200803
William Lallemand85b0bd92017-06-01 17:38:53 +0200804 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemand45059272021-04-21 16:55:34 +0200805 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200806 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200807 if (next_argv == NULL)
808 goto alloc_error;
809
William Lallemand00417412020-06-05 14:08:41 +0200810 /* copy the program name */
811 next_argv[next_argc++] = old_argv[0];
812
813 /* insert the new options just after argv[0] in case we have a -- */
814
William Lallemand73b85e72017-06-01 17:38:51 +0200815 /* add -sf <PID>* to argv */
William Lallemand3f128872019-04-01 11:29:59 +0200816 if (mworker_child_nb() > 0) {
817 struct mworker_proc *child;
818
William Lallemand73b85e72017-06-01 17:38:51 +0200819 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200820
821 list_for_each_entry(child, &proc_list, list) {
William Lallemand677e2f22019-11-19 17:04:18 +0100822 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1 )
William Lallemand3f128872019-04-01 11:29:59 +0200823 continue;
William Lallemand00417412020-06-05 14:08:41 +0200824 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
William Lallemand73b85e72017-06-01 17:38:51 +0200825 goto alloc_error;
826 msg = NULL;
827 }
828 }
William Lallemand2bf6d622017-06-20 11:20:23 +0200829 /* add the -x option with the stat socket */
William Lallemand85b0bd92017-06-01 17:38:53 +0200830 if (cur_unixsocket) {
William Lallemand2bf6d622017-06-20 11:20:23 +0200831 next_argv[next_argc++] = "-x";
832 next_argv[next_argc++] = (char *)cur_unixsocket;
William Lallemand85b0bd92017-06-01 17:38:53 +0200833 }
834
William Lallemand00417412020-06-05 14:08:41 +0200835 /* copy the previous options */
836 for (i = 1; i < old_argc; i++)
837 next_argv[next_argc++] = old_argv[i];
838
Christopher Faulet767a84b2017-11-24 16:50:31 +0100839 ha_warning("Reexecuting Master process\n");
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200840 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100841 execvp(next_argv[0], next_argv);
William Lallemand73b85e72017-06-01 17:38:51 +0200842
Christopher Faulet767a84b2017-11-24 16:50:31 +0100843 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
William Lallemand9fc6c972020-06-08 10:01:13 +0200844 free(next_argv);
845 next_argv = NULL;
William Lallemand722d4ca2017-11-15 19:02:55 +0100846 return;
847
William Lallemand73b85e72017-06-01 17:38:51 +0200848alloc_error:
William Lallemand00417412020-06-05 14:08:41 +0200849 free(next_argv);
850 next_argv = NULL;
Joseph Herlant07a08342018-11-15 10:43:05 -0800851 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200852 return;
853}
854
William Lallemandb3f2be32018-09-11 10:06:18 +0200855static void mworker_loop()
856{
857
858#if defined(USE_SYSTEMD)
859 if (global.tune.options & GTUNE_USE_SYSTEMD)
860 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
861#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200862 /* Busy polling makes no sense in the master :-) */
863 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200864
William Lallemandbc193052018-09-11 10:06:26 +0200865 master = 1;
866
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100867 signal_unregister(SIGTTIN);
868 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100869 signal_unregister(SIGUSR1);
870 signal_unregister(SIGHUP);
871 signal_unregister(SIGQUIT);
872
William Lallemandb3f2be32018-09-11 10:06:18 +0200873 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
874 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100875 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
876 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200877 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
878 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
879 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
880 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
881
882 mworker_unblock_signals();
883 mworker_cleanlisteners();
William Lallemand27f3fa52018-12-06 14:05:20 +0100884 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200885
William Lallemandbc193052018-09-11 10:06:26 +0200886 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
887 some SIGCHLD were lost */
888
William Lallemandb3f2be32018-09-11 10:06:18 +0200889 global.nbthread = 1;
890 relative_pid = 1;
891 pid_bit = 1;
Willy Tarreaua38a7172019-02-02 17:11:28 +0100892 all_proc_mask = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200893
William Lallemand2672eb92018-12-14 15:52:39 +0100894#ifdef USE_THREAD
895 tid_bit = 1;
896 all_threads_mask = 1;
897#endif
898
William Lallemandb3f2be32018-09-11 10:06:18 +0200899 jobs++; /* this is the "master" job, we want to take care of the
900 signals even if there is no listener so the poll loop don't
901 leave */
902
903 fork_poller();
Willy Tarreaub4f7cc32019-05-03 09:27:30 +0200904 run_thread_poll_loop(0);
William Lallemandb3f2be32018-09-11 10:06:18 +0200905}
William Lallemandcb11fd22017-06-01 17:38:52 +0200906
907/*
908 * Reexec the process in failure mode, instead of exiting
909 */
910void reexec_on_failure()
911{
912 if (!atexit_flag)
913 return;
914
915 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
916
Christopher Faulet767a84b2017-11-24 16:50:31 +0100917 ha_warning("Reexecuting Master process in waitpid mode\n");
William Lallemandcb11fd22017-06-01 17:38:52 +0200918 mworker_reload();
William Lallemandcb11fd22017-06-01 17:38:52 +0200919}
William Lallemand73b85e72017-06-01 17:38:51 +0200920
921
922/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200923 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
924 * a signal zero to all subscribers. This means that it's as easy as
925 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100927static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928{
929 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200930 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100931 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932}
933
934/*
935 * upon SIGTTOU, we pause everything
936 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100937static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938{
Willy Tarreau775e0012020-09-24 16:36:26 +0200939 if (protocol_pause_all() & ERR_FATAL) {
940 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200941 ha_warning("%s", msg);
942 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200943 soft_stop();
944 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100945 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200946}
947
948/*
949 * upon SIGTTIN, let's have a soft stop.
950 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100951static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952{
Willy Tarreau775e0012020-09-24 16:36:26 +0200953 if (protocol_resume_all() & ERR_FATAL) {
954 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 +0200955 ha_warning("%s", msg);
956 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958}
959
960/*
961 * this function dumps every server's state when the process receives SIGHUP.
962 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100963static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100965 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200966
Christopher Faulet767a84b2017-11-24 16:50:31 +0100967 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 while (p) {
969 struct server *s = p->srv;
970
971 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
972 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100973 chunk_printf(&trash,
974 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
975 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200976 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100977 s->cur_sess, s->nbpend, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200978 ha_warning("%s\n", trash.area);
979 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980 s = s->next;
981 }
982
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200983 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
984 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100985 chunk_printf(&trash,
986 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
987 p->id,
988 p->feconn, p->beconn, p->totpend, p->nbpend, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200989 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100990 chunk_printf(&trash,
991 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
992 p->id,
993 (p->srv_bck) ? "is running on backup servers" : "has no server available",
994 p->feconn, p->beconn, p->totpend, p->nbpend, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200995 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100996 chunk_printf(&trash,
997 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
998 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
999 p->id, p->srv_act, p->srv_bck,
1000 p->feconn, p->beconn, p->totpend, p->nbpend, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001001 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001002 ha_warning("%s\n", trash.area);
1003 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004
1005 p = p->next;
1006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001007}
1008
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001009static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001010{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +02001011 /* dump memory usage then free everything possible */
1012 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +01001013 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001014}
1015
William Lallemande1340412017-12-28 16:09:36 +01001016/*
1017 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
1018 * If <fd> < 0, it opens /dev/null and use it to dup
1019 *
1020 * In the case of chrooting, you have to open /dev/null before the chroot, and
1021 * pass the <fd> to this function
1022 */
1023static void stdio_quiet(int fd)
1024{
1025 if (fd < 0)
1026 fd = open("/dev/null", O_RDWR, 0);
1027
1028 if (fd > -1) {
1029 fclose(stdin);
1030 fclose(stdout);
1031 fclose(stderr);
1032
1033 dup2(fd, 0);
1034 dup2(fd, 1);
1035 dup2(fd, 2);
1036 if (fd > 2)
1037 close(fd);
1038 return;
1039 }
1040
1041 ha_alert("Cannot open /dev/null\n");
1042 exit(EXIT_FAILURE);
1043}
1044
1045
Joseph Herlant03420902018-11-15 10:41:50 -08001046/* This function checks if cfg_cfgfiles contains directories.
1047 * If it finds one, it adds all the files (and only files) it contains
1048 * in cfg_cfgfiles in place of the directory (and removes the directory).
1049 * It adds the files in lexical order.
1050 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001051 * It doesn't add files with name starting with '.'
1052 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001053static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001054{
1055 struct wordlist *wl, *wlb;
1056 char *err = NULL;
1057
1058 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1059 struct stat file_stat;
1060 struct dirent **dir_entries = NULL;
1061 int dir_entries_nb;
1062 int dir_entries_it;
1063
1064 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001065 ha_alert("Cannot open configuration file/directory %s : %s\n",
1066 wl->s,
1067 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001068 exit(1);
1069 }
1070
1071 if (!S_ISDIR(file_stat.st_mode))
1072 continue;
1073
1074 /* from this point wl->s is a directory */
1075
1076 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1077 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001078 ha_alert("Cannot open configuration directory %s : %s\n",
1079 wl->s,
1080 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001081 exit(1);
1082 }
1083
1084 /* for each element in the directory wl->s */
1085 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1086 struct dirent *dir_entry = dir_entries[dir_entries_it];
1087 char *filename = NULL;
1088 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1089
1090 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001091 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001092 */
1093 if (dir_entry->d_name[0] == '.' ||
1094 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1095 goto next_dir_entry;
1096
1097 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001098 ha_alert("Cannot load configuration files %s : out of memory.\n",
1099 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001100 exit(1);
1101 }
1102
1103 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001104 ha_alert("Cannot open configuration file %s : %s\n",
1105 wl->s,
1106 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001107 exit(1);
1108 }
1109
1110 /* don't add anything else than regular file in cfg_cfgfiles
1111 * this way we avoid loops
1112 */
1113 if (!S_ISREG(file_stat.st_mode))
1114 goto next_dir_entry;
1115
1116 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001117 ha_alert("Cannot load configuration files %s : %s\n",
1118 filename,
1119 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001120 exit(1);
1121 }
1122
1123next_dir_entry:
1124 free(filename);
1125 free(dir_entry);
1126 }
1127
1128 free(dir_entries);
1129
1130 /* remove the current directory (wl) from cfg_cfgfiles */
1131 free(wl->s);
1132 LIST_DEL(&wl->list);
1133 free(wl);
1134 }
1135
1136 free(err);
1137}
1138
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139/*
William Lallemand73b85e72017-06-01 17:38:51 +02001140 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001141 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001142 * Return an allocated copy of argv
1143 */
1144
1145static char **copy_argv(int argc, char **argv)
1146{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001147 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001148
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001149 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001150 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001151 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001152 return NULL;
1153 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001154 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001155
William Lallemanddf6c5a82020-06-04 17:40:23 +02001156 /* first copy argv[0] */
1157 *newargv++ = *argv++;
1158 argc--;
1159
1160 while (argc > 0) {
1161 if (**argv != '-') {
1162 /* non options are copied but will fail in the argument parser */
1163 *newargv++ = *argv++;
1164 argc--;
1165
1166 } else {
1167 char *flag;
1168
1169 flag = *argv + 1;
1170
1171 if (flag[0] == '-' && flag[1] == 0) {
1172 /* "--\0" copy every arguments till the end of argv */
1173 *newargv++ = *argv++;
1174 argc--;
1175
1176 while (argc > 0) {
1177 *newargv++ = *argv++;
1178 argc--;
1179 }
1180 } else {
1181 switch (*flag) {
1182 case 's':
1183 /* -sf / -st and their parameters are ignored */
1184 if (flag[1] == 'f' || flag[1] == 't') {
1185 argc--;
1186 argv++;
1187 /* The list can't contain a negative value since the only
1188 way to know the end of this list is by looking for the
1189 next option or the end of the options */
1190 while (argc > 0 && argv[0][0] != '-') {
1191 argc--;
1192 argv++;
1193 }
William Lallemand398da622020-09-02 16:12:23 +02001194 } else {
1195 argc--;
1196 argv++;
1197
William Lallemanddf6c5a82020-06-04 17:40:23 +02001198 }
1199 break;
1200
1201 case 'x':
1202 /* this option and its parameter are ignored */
1203 argc--;
1204 argv++;
1205 if (argc > 0) {
1206 argc--;
1207 argv++;
1208 }
1209 break;
1210
1211 case 'C':
1212 case 'n':
1213 case 'm':
1214 case 'N':
1215 case 'L':
1216 case 'f':
1217 case 'p':
1218 case 'S':
1219 /* these options have only 1 parameter which must be copied and can start with a '-' */
1220 *newargv++ = *argv++;
1221 argc--;
1222 if (argc == 0)
1223 goto error;
1224 *newargv++ = *argv++;
1225 argc--;
1226 break;
1227 default:
1228 /* for other options just copy them without parameters, this is also done
1229 * for options like "--foo", but this will fail in the argument parser.
1230 * */
1231 *newargv++ = *argv++;
1232 argc--;
1233 break;
1234 }
William Lallemand73b85e72017-06-01 17:38:51 +02001235 }
1236 }
William Lallemand73b85e72017-06-01 17:38:51 +02001237 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001238
William Lallemanddf6c5a82020-06-04 17:40:23 +02001239 return retargv;
1240
1241error:
1242 free(retargv);
1243 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001244}
1245
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001246
1247/* Performs basic random seed initialization. The main issue with this is that
1248 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1249 * which means that there will only be 4 billion possible random sequences once
1250 * srandom() is called, regardless of the internal state. Not calling it is
1251 * even worse as we'll always produce the same randoms sequences. What we do
1252 * here is to create an initial sequence from various entropy sources, hash it
1253 * using SHA1 and keep the resulting 160 bits available globally.
1254 *
1255 * We initialize the current process with the first 32 bits before starting the
1256 * polling loop, where all this will be changed to have process specific and
1257 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001258 *
1259 * Before starting threads, it's still possible to call random() as srandom()
1260 * is initialized from this, but after threads and/or processes are started,
1261 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001262 */
1263static void ha_random_boot(char *const *argv)
1264{
1265 unsigned char message[256];
1266 unsigned char *m = message;
1267 struct timeval tv;
1268 blk_SHA_CTX ctx;
1269 unsigned long l;
1270 int fd;
1271 int i;
1272
1273 /* start with current time as pseudo-random seed */
1274 gettimeofday(&tv, NULL);
1275 write_u32(m, tv.tv_sec); m += 4;
1276 write_u32(m, tv.tv_usec); m += 4;
1277
1278 /* PID and PPID add some OS-based randomness */
1279 write_u16(m, getpid()); m += 2;
1280 write_u16(m, getppid()); m += 2;
1281
1282 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1283 fd = open("/dev/urandom", O_RDONLY);
1284 if (fd >= 0) {
1285 i = read(fd, m, 20);
1286 if (i > 0)
1287 m += i;
1288 close(fd);
1289 }
1290
1291 /* take up to 160 bits bytes from openssl (non-blocking) */
1292#ifdef USE_OPENSSL
1293 if (RAND_bytes(m, 20) == 1)
1294 m += 20;
1295#endif
1296
1297 /* take 160 bits from existing random in case it was already initialized */
1298 for (i = 0; i < 5; i++) {
1299 write_u32(m, random());
1300 m += 4;
1301 }
1302
1303 /* stack address (benefit form operating system's ASLR) */
1304 l = (unsigned long)&m;
1305 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1306
1307 /* argv address (benefit form operating system's ASLR) */
1308 l = (unsigned long)&argv;
1309 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1310
1311 /* use tv_usec again after all the operations above */
1312 gettimeofday(&tv, NULL);
1313 write_u32(m, tv.tv_usec); m += 4;
1314
1315 /*
1316 * At this point, ~84-92 bytes have been used
1317 */
1318
1319 /* finish with the hostname */
1320 strncpy((char *)m, hostname, message + sizeof(message) - m);
1321 m += strlen(hostname);
1322
1323 /* total message length */
1324 l = m - message;
1325
1326 memset(&ctx, 0, sizeof(ctx));
1327 blk_SHA1_Init(&ctx);
1328 blk_SHA1_Update(&ctx, message, l);
1329 blk_SHA1_Final(boot_seed, &ctx);
1330
1331 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001332 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001333}
1334
Willy Tarreau5a023f02019-03-01 14:19:31 +01001335/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1336 * setting, and returns it. It may return -1 meaning "unlimited" if some
1337 * unlimited proxies have been found and the global.maxconn value is not yet
1338 * set. It may also return a value greater than maxconn if it's not yet set.
1339 * Note that a value of zero means there is no need for pipes. -1 is never
1340 * returned if global.maxconn is valid.
1341 */
1342static int compute_ideal_maxpipes()
1343{
1344 struct proxy *cur;
1345 int nbfe = 0, nbbe = 0;
1346 int unlimited = 0;
1347 int pipes;
1348 int max;
1349
1350 for (cur = proxies_list; cur; cur = cur->next) {
1351 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1352 if (cur->cap & PR_CAP_FE) {
1353 max = cur->maxconn;
1354 nbfe += max;
1355 if (!max) {
1356 unlimited = 1;
1357 break;
1358 }
1359 }
1360 if (cur->cap & PR_CAP_BE) {
1361 max = cur->fullconn ? cur->fullconn : global.maxconn;
1362 nbbe += max;
1363 if (!max) {
1364 unlimited = 1;
1365 break;
1366 }
1367 }
1368 }
1369 }
1370
1371 pipes = MAX(nbfe, nbbe);
1372 if (global.maxconn) {
1373 if (pipes > global.maxconn || unlimited)
1374 pipes = global.maxconn;
1375 } else if (unlimited) {
1376 pipes = -1;
1377 }
1378
1379 return pipes >= 4 ? pipes / 4 : pipes;
1380}
1381
Willy Tarreauac350932019-03-01 15:43:14 +01001382/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1383 * rlimits and computes an ideal maxconn. It's meant to be called only when
1384 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001385 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1386 * default 100) is returned as it is expected that it will even run on tight
1387 * environments, and will maintain compatibility with previous packages that
1388 * used to rely on this value as the default one. The system will emit a
1389 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001390 */
1391static int compute_ideal_maxconn()
1392{
1393 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1394 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1395 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001396 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001397 int maxconn;
1398
1399 /* we have to take into account these elements :
1400 * - number of engine_fds, which inflates the number of FD needed per
1401 * connection by this number.
1402 * - number of pipes per connection on average : for the unlimited
1403 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1404 * fixed value of 2*pipes.
1405 * - two FDs per connection
1406 */
1407
1408 /* subtract listeners and checks */
1409 remain -= global.maxsock;
1410
Willy Tarreau3f200852019-03-14 19:13:17 +01001411 /* one epoll_fd/kqueue_fd per thread */
1412 remain -= global.nbthread;
1413
1414 /* one wake-up pipe (2 fd) per thread */
1415 remain -= 2 * global.nbthread;
1416
Willy Tarreauac350932019-03-01 15:43:14 +01001417 /* Fixed pipes values : we only subtract them if they're not larger
1418 * than the remaining FDs because pipes are optional.
1419 */
1420 if (pipes >= 0 && pipes * 2 < remain)
1421 remain -= pipes * 2;
1422
1423 if (pipes < 0) {
1424 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1425 * = maxconn * (2 + 0.5 + engine_fds)
1426 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1427 */
1428 maxconn = 2 * remain / (5 + 2 * engine_fds);
1429 } else {
1430 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1431 * = maxconn * (2 + engine_fds)
1432 */
1433 maxconn = remain / (2 + engine_fds);
1434 }
1435
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001436 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001437}
1438
Willy Tarreaua409f302020-03-10 17:08:53 +01001439/* computes the estimated maxsock value for the given maxconn based on the
1440 * possibly set global.maxpipes and existing partial global.maxsock. It may
1441 * temporarily change global.maxconn for the time needed to propagate the
1442 * computations, and will reset it.
1443 */
1444static int compute_ideal_maxsock(int maxconn)
1445{
1446 int maxpipes = global.maxpipes;
1447 int maxsock = global.maxsock;
1448
1449
1450 if (!maxpipes) {
1451 int old_maxconn = global.maxconn;
1452
1453 global.maxconn = maxconn;
1454 maxpipes = compute_ideal_maxpipes();
1455 global.maxconn = old_maxconn;
1456 }
1457
1458 maxsock += maxconn * 2; /* each connection needs two sockets */
1459 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1460 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1461 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1462
1463 /* compute fd used by async engines */
1464 if (global.ssl_used_async_engines) {
1465 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1466
1467 maxsock += maxconn * sides * global.ssl_used_async_engines;
1468 }
1469 return maxsock;
1470}
1471
Willy Tarreau304e17e2020-03-10 17:54:54 +01001472/* Tests if it is possible to set the current process' RLIMIT_NOFILE to
1473 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1474 * value is accepted, non-zero otherwise. This is used to determine if an
1475 * automatic limit may be applied or not. When it is not, the caller knows that
1476 * the highest we can do is the rlim_max at boot. In case of error, we return
1477 * that the setting is possible, so that we defer the error processing to the
1478 * final stage in charge of enforcing this.
1479 */
1480static int check_if_maxsock_permitted(int maxsock)
1481{
1482 struct rlimit orig_limit, test_limit;
1483 int ret;
1484
1485 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1486 return 1;
1487
1488 /* don't go further if we can't even set to what we have */
1489 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1490 return 1;
1491
1492 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1493 test_limit.rlim_cur = test_limit.rlim_max;
1494 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1495
1496 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1497 return 1;
1498
1499 return ret == 0;
1500}
1501
1502
William Lallemand73b85e72017-06-01 17:38:51 +02001503/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504 * This function initializes all the necessary variables. It only returns
1505 * if everything is OK. If something fails, it exits.
1506 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001507static void init(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001508{
Willy Tarreaubaaee002006-06-26 02:48:02 +02001509 int arg_mode = 0; /* MODE_DEBUG, ... */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001510 char *tmp;
1511 char *cfg_pidfile = NULL;
Willy Tarreau058e9072009-07-20 09:30:05 +02001512 int err_code = 0;
Maxime de Roucy0f503922016-05-13 23:52:55 +02001513 char *err_msg = NULL;
Willy Tarreau477ecd82010-01-03 21:12:30 +01001514 struct wordlist *wl;
Kevinm48936af2010-12-22 16:08:21 +00001515 char *progname;
Willy Tarreau576132e2011-09-10 19:26:56 +02001516 char *change_dir = NULL;
Christopher Fauletd7c91962015-04-30 11:48:27 +02001517 struct proxy *px;
Willy Tarreaue6945732016-12-21 19:57:00 +01001518 struct post_check_fct *pcf;
Willy Tarreauac350932019-03-01 15:43:14 +01001519 int ideal_maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001520
Christopher Faulete3a5e352017-10-24 13:53:54 +02001521 global.mode = MODE_STARTING;
William Lallemand00417412020-06-05 14:08:41 +02001522 old_argv = copy_argv(argc, argv);
1523 if (!old_argv) {
William Lallemanddf6c5a82020-06-04 17:40:23 +02001524 ha_alert("failed to copy argv.\n");
1525 exit(1);
1526 }
William Lallemand73b85e72017-06-01 17:38:51 +02001527
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001528 if (!init_trash_buffers(1)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001529 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet748919a2017-07-26 14:59:46 +02001530 exit(1);
1531 }
David du Colombier7af46052012-05-16 14:16:48 +02001532
Emeric Brun2b920a12010-09-23 18:30:22 +02001533 /* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
1534 * the string in case of truncation, and at least FreeBSD appears not to do
1535 * it.
1536 */
1537 memset(hostname, 0, sizeof(hostname));
1538 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001539
1540 if ((localpeer = strdup(hostname)) == NULL) {
1541 ha_alert("Cannot allocate memory for local peer.\n");
1542 exit(EXIT_FAILURE);
1543 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001544 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Emeric Brun2b920a12010-09-23 18:30:22 +02001545
William Lallemand24c928c2020-01-14 17:58:18 +01001546 /* we were in mworker mode, we should restart in mworker mode */
1547 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1548 global.mode |= MODE_MWORKER;
1549
Willy Tarreaubaaee002006-06-26 02:48:02 +02001550 /*
1551 * Initialize the previously static variables.
1552 */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001553
Willy Tarreau173d9952018-01-26 21:48:23 +01001554 totalconn = actconn = listeners = stopping = 0;
Cyril Bonté203ec5a2017-03-23 22:44:13 +01001555 killed = 0;
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001556
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557
1558#ifdef HAPROXY_MEMMAX
Willy Tarreau70060452015-12-14 12:46:07 +01001559 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560#endif
1561
Benoit GARNIERb413c2a2016-03-27 11:08:03 +02001562 tzset();
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02001563 tv_update_date(-1,-1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001564 start_date = now;
1565
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001566 ha_random_boot(argv);
Willy Tarreau84310e22014-02-14 11:59:04 +01001567
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001568 if (init_acl() != 0)
1569 exit(1);
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001570
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001571 /* Initialise lua. */
1572 hlua_init();
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001573
Christopher Fauletff2613e2016-11-09 11:36:17 +01001574 /* Initialize process vars */
1575 vars_init(&global.vars, SCOPE_PROC);
1576
Willy Tarreau43b78992009-01-25 15:42:27 +01001577 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001578#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001579 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001581#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001582 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001584#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001585 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001586#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001587#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001588 global.tune.options |= GTUNE_USE_EVPORTS;
1589#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001590#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001591 global.tune.options |= GTUNE_USE_SPLICE;
1592#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001593#if defined(USE_GETADDRINFO)
1594 global.tune.options |= GTUNE_USE_GAI;
1595#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001596#if defined(SO_REUSEPORT)
1597 global.tune.options |= GTUNE_USE_REUSEPORT;
1598#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001599#ifdef USE_THREAD
1600 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1601#endif
William Dauchya5194602020-03-28 19:29:58 +01001602 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603
1604 pid = getpid();
1605 progname = *argv;
1606 while ((tmp = strchr(progname, '/')) != NULL)
1607 progname = tmp + 1;
1608
Kevinm48936af2010-12-22 16:08:21 +00001609 /* the process name is used for the logs only */
Eric Salama7cea6062020-10-02 11:58:19 +02001610 chunk_initlen(&global.log_tag, strdup(progname), strlen(progname), strlen(progname));
1611 if (b_orig(&global.log_tag) == NULL) {
1612 chunk_destroy(&global.log_tag);
1613 ha_alert("Cannot allocate memory for log_tag.\n");
1614 exit(EXIT_FAILURE);
1615 }
Kevinm48936af2010-12-22 16:08:21 +00001616
Willy Tarreaubaaee002006-06-26 02:48:02 +02001617 argc--; argv++;
1618 while (argc > 0) {
1619 char *flag;
1620
1621 if (**argv == '-') {
1622 flag = *argv+1;
1623
1624 /* 1 arg */
1625 if (*flag == 'v') {
1626 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001627 if (flag[1] == 'v') /* -vv */
1628 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001629 exit(0);
1630 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001631#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001633 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001635#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001637 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001639#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001640 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001641 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001642#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001643#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001644 else if (*flag == 'd' && flag[1] == 'v')
1645 global.tune.options &= ~GTUNE_USE_EVPORTS;
1646#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001647#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001648 else if (*flag == 'd' && flag[1] == 'S')
1649 global.tune.options &= ~GTUNE_USE_SPLICE;
1650#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001651#if defined(USE_GETADDRINFO)
1652 else if (*flag == 'd' && flag[1] == 'G')
1653 global.tune.options &= ~GTUNE_USE_GAI;
1654#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001655#if defined(SO_REUSEPORT)
1656 else if (*flag == 'd' && flag[1] == 'R')
1657 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1658#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001659 else if (*flag == 'd' && flag[1] == 'V')
1660 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001661 else if (*flag == 'V')
1662 arg_mode |= MODE_VERBOSE;
1663 else if (*flag == 'd' && flag[1] == 'b')
1664 arg_mode |= MODE_FOREGROUND;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001665 else if (*flag == 'd' && flag[1] == 'W')
1666 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreau6e064432012-05-08 15:40:42 +02001667 else if (*flag == 'd' && flag[1] == 'M')
1668 mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001669 else if (*flag == 'd' && flag[1] == 'r')
1670 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001671 else if (*flag == 'd')
1672 arg_mode |= MODE_DEBUG;
1673 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 }
1713 LIST_ADD(&mworker_cli_conf, &c->list);
1714
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 Tarreaubaaee002006-06-26 02:48:02 +02001794 case 'p' : cfg_pidfile = *argv; break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001795 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001796 }
1797 }
1798 }
1799 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001800 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801 argv++; argc--;
1802 }
1803
Christopher Faulete3a5e352017-10-24 13:53:54 +02001804 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001805 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806
William Lallemand944e6192018-11-21 15:48:31 +01001807 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001808 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001809 global.mode |= MODE_MWORKER_WAIT;
1810 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001811 }
1812
Willy Tarreaue63b9c92021-07-21 10:01:36 +02001813 if ((global.mode & (MODE_MWORKER | MODE_CHECK)) == MODE_MWORKER &&
1814 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001815 atexit_flag = 1;
1816 atexit(reexec_on_failure);
1817 }
1818
Willy Tarreau576132e2011-09-10 19:26:56 +02001819 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001820 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001821 exit(1);
1822 }
1823
Willy Tarreaubaaee002006-06-26 02:48:02 +02001824 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001825
1826 init_default_instance();
1827
William Lallemand944e6192018-11-21 15:48:31 +01001828 /* in wait mode, we don't try to read the configuration files */
1829 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet33edd512021-01-12 18:57:38 +01001830 char *env_cfgfiles = NULL;
1831 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001832
William Lallemand944e6192018-11-21 15:48:31 +01001833 /* handle cfgfiles that are actually directories */
1834 cfgfiles_expand_directories();
1835
1836 if (LIST_ISEMPTY(&cfg_cfgfiles))
1837 usage(progname);
1838
1839
1840 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1841 int ret;
1842
Christopher Faulet33edd512021-01-12 18:57:38 +01001843 if (env_err == 0) {
1844 if (!memprintf(&env_cfgfiles, "%s%s%s",
1845 (env_cfgfiles ? env_cfgfiles : ""),
1846 (env_cfgfiles ? ";" : ""), wl->s))
1847 env_err = 1;
1848 }
William Lallemand7b302d82019-05-20 11:15:37 +02001849
William Lallemand944e6192018-11-21 15:48:31 +01001850 ret = readcfgfile(wl->s);
1851 if (ret == -1) {
1852 ha_alert("Could not open configuration file %s : %s\n",
1853 wl->s, strerror(errno));
Christopher Faulet33edd512021-01-12 18:57:38 +01001854 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001855 exit(1);
1856 }
1857 if (ret & (ERR_ABORT|ERR_FATAL))
1858 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1859 err_code |= ret;
Christopher Faulet33edd512021-01-12 18:57:38 +01001860 if (err_code & ERR_ABORT) {
1861 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001862 exit(1);
Christopher Faulet33edd512021-01-12 18:57:38 +01001863 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001864 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001865
William Lallemand944e6192018-11-21 15:48:31 +01001866 /* do not try to resolve arguments nor to spot inconsistencies when
1867 * the configuration contains fatal errors caused by files not found
1868 * or failed memory allocations.
1869 */
1870 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1871 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet33edd512021-01-12 18:57:38 +01001872 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001873 exit(1);
1874 }
Christopher Faulet33edd512021-01-12 18:57:38 +01001875 if (env_err) {
1876 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1877 exit(1);
1878 }
1879 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1880 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001881
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001882 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001883 if (global.mode & MODE_MWORKER) {
1884 int proc;
William Lallemand16dd1b32018-11-19 18:46:18 +01001885 struct mworker_proc *tmproc;
1886
William Lallemand482f9a92019-04-12 16:15:00 +02001887 setenv("HAPROXY_MWORKER", "1", 1);
1888
William Lallemand16dd1b32018-11-19 18:46:18 +01001889 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1890
William Lallemandf3a86832019-04-01 11:29:58 +02001891 tmproc = calloc(1, sizeof(*tmproc));
William Lallemand16dd1b32018-11-19 18:46:18 +01001892 if (!tmproc) {
1893 ha_alert("Cannot allocate process structures.\n");
1894 exit(EXIT_FAILURE);
1895 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001896 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01001897 tmproc->reloads = 0;
1898 tmproc->relative_pid = 0;
1899 tmproc->pid = pid;
1900 tmproc->timestamp = start_date.tv_sec;
1901 tmproc->ipc_fd[0] = -1;
1902 tmproc->ipc_fd[1] = -1;
1903
1904 proc_self = tmproc;
1905
1906 LIST_ADDQ(&proc_list, &tmproc->list);
1907 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001908
1909 for (proc = 0; proc < global.nbproc; proc++) {
William Lallemandce83b4a2018-10-26 14:47:30 +02001910
William Lallemandf3a86832019-04-01 11:29:58 +02001911 tmproc = calloc(1, sizeof(*tmproc));
William Lallemandce83b4a2018-10-26 14:47:30 +02001912 if (!tmproc) {
1913 ha_alert("Cannot allocate process structures.\n");
1914 exit(EXIT_FAILURE);
1915 }
1916
William Lallemand8f7069a2019-04-12 16:09:23 +02001917 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02001918 tmproc->pid = -1;
1919 tmproc->reloads = 0;
William Lallemande3683302018-11-19 18:46:17 +01001920 tmproc->timestamp = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001921 tmproc->relative_pid = 1 + proc;
William Lallemand550db6d2018-11-06 17:37:12 +01001922 tmproc->ipc_fd[0] = -1;
1923 tmproc->ipc_fd[1] = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001924
1925 if (mworker_cli_sockpair_new(tmproc, proc) < 0) {
1926 exit(EXIT_FAILURE);
1927 }
1928
1929 LIST_ADDQ(&proc_list, &tmproc->list);
1930 }
William Lallemand944e6192018-11-21 15:48:31 +01001931 }
1932 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1933 struct wordlist *it, *c;
1934
Remi Tricot-Le Breton80dc1452021-05-19 10:45:12 +02001935 /* get the info of the children in the env */
1936 if (mworker_env_to_proc_list() < 0) {
1937 exit(EXIT_FAILURE);
1938 }
William Lallemande7361152018-10-26 14:47:36 +02001939
William Lallemand550db6d2018-11-06 17:37:12 +01001940 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02001941
William Lallemand550db6d2018-11-06 17:37:12 +01001942 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02001943 ha_alert("Can't create the master's CLI.\n");
1944 exit(EXIT_FAILURE);
1945 }
William Lallemande7361152018-10-26 14:47:36 +02001946
William Lallemand550db6d2018-11-06 17:37:12 +01001947 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
1948
1949 if (mworker_cli_proxy_new_listener(c->s) < 0) {
1950 ha_alert("Can't create the master's CLI.\n");
1951 exit(EXIT_FAILURE);
1952 }
1953 LIST_DEL(&c->list);
1954 free(c->s);
1955 free(c);
1956 }
1957 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001958 }
1959
Willy Tarreauf42d7942020-10-20 11:54:49 +02001960 if (global.nbproc > 1 && !global.nbthread) {
1961 ha_warning("nbproc is deprecated!\n"
1962 " | For suffering many limitations, the 'nbproc' directive is now deprecated\n"
1963 " | and scheduled for removal in 2.5. Just comment it out: haproxy will use\n"
1964 " | threads and will run on all allocated processors. You may also switch to\n"
1965 " | 'nbthread %d' to keep the same number of processors. If you absolutely\n"
1966 " | want to run in multi-process mode, you can silence this warning by adding\n"
1967 " | 'nbthread 1', but then please report your use case to developers.\n",
1968 global.nbproc);
1969 }
1970
Willy Tarreaubb925012009-07-23 13:36:36 +02001971 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02001972 for (px = proxies_list; px; px = px->next) {
1973 struct server *srv;
1974 struct post_proxy_check_fct *ppcf;
1975 struct post_server_check_fct *pscf;
1976
Christopher Fauletd5bd8242020-11-02 16:20:13 +01001977 if (px->disabled)
1978 continue;
1979
Christopher Fauletc1692962019-08-12 09:51:07 +02001980 list_for_each_entry(pscf, &post_server_check_list, list) {
1981 for (srv = px->srv; srv; srv = srv->next)
1982 err_code |= pscf->fct(srv);
1983 }
1984 list_for_each_entry(ppcf, &post_proxy_check_list, list)
1985 err_code |= ppcf->fct(px);
1986 }
Willy Tarreaubb925012009-07-23 13:36:36 +02001987 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001988 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001989 exit(1);
1990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01001992 err_code |= pattern_finalize_config();
1993 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1994 ha_alert("Failed to finalize pattern config.\n");
1995 exit(1);
1996 }
Willy Tarreau0f936722019-04-11 14:47:08 +02001997
Willy Tarreau70060452015-12-14 12:46:07 +01001998 /* recompute the amount of per-process memory depending on nbproc and
1999 * the shared SSL cache size (allowed to exist in all processes).
2000 */
2001 if (global.rlimit_memmax_all) {
2002#if defined (USE_OPENSSL) && !defined(USE_PRIVATE_CACHE)
2003 int64_t ssl_cache_bytes = global.tune.sslcachesize * 200LL;
2004
2005 global.rlimit_memmax =
2006 ((((int64_t)global.rlimit_memmax_all * 1048576LL) -
2007 ssl_cache_bytes) / global.nbproc +
2008 ssl_cache_bytes + 1048575LL) / 1048576LL;
2009#else
2010 global.rlimit_memmax = global.rlimit_memmax_all / global.nbproc;
2011#endif
2012 }
2013
Willy Tarreaue5733232019-05-22 19:24:06 +02002014#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002015 err_code |= netns_init();
2016 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002017 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002018 exit(1);
2019 }
2020#endif
2021
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002022 /* Apply server states */
2023 apply_server_state();
2024
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002025 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002026 srv_compute_all_admin_states(px);
2027
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002028 /* Apply servers' configured address */
2029 err_code |= srv_init_addr();
2030 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002031 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002032 exit(1);
2033 }
2034
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002035 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2036 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2037 exit(1);
2038 }
2039
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002041 struct peers *pr;
2042 struct proxy *px;
2043
Willy Tarreaubebd2122020-04-15 16:06:11 +02002044 if (warned & WARN_ANY)
2045 qfprintf(stdout, "Warnings were found.\n");
2046
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002047 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002048 if (pr->peers_fe)
2049 break;
2050
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002051 for (px = proxies_list; px; px = px->next)
Willy Tarreauc3914d42020-09-24 08:39:22 +02002052 if (!px->disabled && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002053 break;
2054
2055 if (pr || px) {
2056 /* At least one peer or one listener has been found */
2057 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002058 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002059 }
2060 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2061 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002063
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002064 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002065 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002066
Willy Tarreaue6945732016-12-21 19:57:00 +01002067 list_for_each_entry(pcf, &post_check_list, list) {
2068 err_code |= pcf->fct();
2069 if (err_code & (ERR_ABORT|ERR_FATAL))
2070 exit(1);
2071 }
2072
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073 if (cfg_maxconn > 0)
2074 global.maxconn = cfg_maxconn;
2075
Willy Tarreau8d687d82019-03-01 09:39:42 +01002076 if (global.stats_fe)
2077 global.maxsock += global.stats_fe->maxconn;
2078
2079 if (cfg_peers) {
2080 /* peers also need to bypass global maxconn */
2081 struct peers *p = cfg_peers;
2082
2083 for (p = cfg_peers; p; p = p->next)
2084 if (p->peers_fe)
2085 global.maxsock += p->peers_fe->maxconn;
2086 }
2087
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 if (cfg_pidfile) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002089 free(global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002090 global.pidfile = strdup(cfg_pidfile);
2091 }
2092
Willy Tarreaud0256482015-01-15 21:45:22 +01002093 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002094 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2095 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2096 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2097 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002098 *
2099 * If memmax is set, then it depends on which values are set. If
2100 * maxsslconn is set, we use memmax to determine how many cleartext
2101 * connections may be added, and set maxconn to the sum of the two.
2102 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2103 * the remaining amount of memory between memmax and the cleartext
2104 * connections. If neither are set, then it is considered that all
2105 * connections are SSL-capable, and maxconn is computed based on this,
2106 * then maxsslconn accordingly. We need to know if SSL is used on the
2107 * frontends, backends, or both, because when it's used on both sides,
2108 * we need twice the value for maxsslconn, but we only count the
2109 * handshake once since it is not performed on the two sides at the
2110 * same time (frontend-side is terminated before backend-side begins).
2111 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002112 * ssl_handshake_cost during its initialization. In any case, if
2113 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2114 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002115 */
Willy Tarreauac350932019-03-01 15:43:14 +01002116 ideal_maxconn = compute_ideal_maxconn();
2117
Willy Tarreaud0256482015-01-15 21:45:22 +01002118 if (!global.rlimit_memmax) {
2119 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002120 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002121 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2122 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2123 }
2124 }
2125#ifdef USE_OPENSSL
2126 else if (!global.maxconn && !global.maxsslconn &&
2127 (global.ssl_used_frontend || global.ssl_used_backend)) {
2128 /* memmax is set, compute everything automatically. Here we want
2129 * to ensure that all SSL connections will be served. We take
2130 * care of the number of sides where SSL is used, and consider
2131 * the worst case : SSL used on both sides and doing a handshake
2132 * simultaneously. Note that we can't have more than maxconn
2133 * handshakes at a time by definition, so for the worst case of
2134 * two SSL conns per connection, we count a single handshake.
2135 */
2136 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2137 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002138 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002139
2140 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2141 mem -= global.maxzlibmem;
2142 mem = mem * MEM_USABLE_RATIO;
2143
Willy Tarreau304e17e2020-03-10 17:54:54 +01002144 /* Principle: we test once to set maxconn according to the free
2145 * memory. If it results in values the system rejects, we try a
2146 * second time by respecting rlim_fd_max. If it fails again, we
2147 * go back to the initial value and will let the final code
2148 * dealing with rlimit report the error. That's up to 3 attempts.
2149 */
2150 do {
2151 global.maxconn = mem /
2152 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2153 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2154 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002155
Willy Tarreau304e17e2020-03-10 17:54:54 +01002156 if (retried == 1)
2157 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2158 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002159#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002160 if (global.maxconn > SYSTEM_MAXCONN)
2161 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002162#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002163 global.maxsslconn = sides * global.maxconn;
2164
2165 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2166 break;
2167 } while (retried++ < 2);
2168
Willy Tarreaud0256482015-01-15 21:45:22 +01002169 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2170 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2171 global.maxconn, global.maxsslconn);
2172 }
2173 else if (!global.maxsslconn &&
2174 (global.ssl_used_frontend || global.ssl_used_backend)) {
2175 /* memmax and maxconn are known, compute maxsslconn automatically.
2176 * maxsslconn being forced, we don't know how many of it will be
2177 * on each side if both sides are being used. The worst case is
2178 * when all connections use only one SSL instance because
2179 * handshakes may be on two sides at the same time.
2180 */
2181 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2182 int64_t mem = global.rlimit_memmax * 1048576ULL;
2183 int64_t sslmem;
2184
2185 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2186 mem -= global.maxzlibmem;
2187 mem = mem * MEM_USABLE_RATIO;
2188
Willy Tarreau87b09662015-04-03 00:22:06 +02002189 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002190 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2191 global.maxsslconn = round_2dig(global.maxsslconn);
2192
2193 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002194 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2195 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2196 "without SSL is %d, but %d was found and SSL is in use.\n",
2197 global.rlimit_memmax,
2198 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2199 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002200 exit(1);
2201 }
2202
2203 if (global.maxsslconn > sides * global.maxconn)
2204 global.maxsslconn = sides * global.maxconn;
2205
2206 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2207 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2208 }
2209#endif
2210 else if (!global.maxconn) {
2211 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2212 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2213 int64_t mem = global.rlimit_memmax * 1048576ULL;
2214 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002215 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002216
2217 if (global.ssl_used_frontend || global.ssl_used_backend)
2218 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2219
2220 mem -= global.maxzlibmem;
2221 mem = mem * MEM_USABLE_RATIO;
2222
2223 clearmem = mem;
2224 if (sides)
2225 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2226
Willy Tarreau304e17e2020-03-10 17:54:54 +01002227 /* Principle: we test once to set maxconn according to the free
2228 * memory. If it results in values the system rejects, we try a
2229 * second time by respecting rlim_fd_max. If it fails again, we
2230 * go back to the initial value and will let the final code
2231 * dealing with rlimit report the error. That's up to 3 attempts.
2232 */
2233 do {
2234 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2235 if (retried == 1)
2236 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2237 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002238#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002239 if (global.maxconn > SYSTEM_MAXCONN)
2240 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002241#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002242
Willy Tarreau304e17e2020-03-10 17:54:54 +01002243 if (clearmem <= 0 || !global.maxconn) {
2244 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2245 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2246 "is %d, but %d was found.\n",
2247 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002248 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002249 global.maxsslconn);
2250 exit(1);
2251 }
2252
2253 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2254 break;
2255 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002256
2257 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2258 if (sides && global.maxsslconn > sides * global.maxconn) {
2259 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2260 "to be limited to %d. Better reduce global.maxsslconn to get more "
2261 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2262 }
2263 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2264 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002265 }
2266
Willy Tarreaua409f302020-03-10 17:08:53 +01002267 global.maxsock = compute_ideal_maxsock(global.maxconn);
2268 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002269 if (!global.maxpipes)
2270 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002271
Olivier Houchard88698d92019-04-16 19:07:22 +02002272 /* update connection pool thresholds */
2273 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2274 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2275
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002276 proxy_adjust_all_maxconn();
2277
Willy Tarreau1db37712007-06-03 17:16:49 +02002278 if (global.tune.maxpollevents <= 0)
2279 global.tune.maxpollevents = MAX_POLL_EVENTS;
2280
Willy Tarreau20076a02021-03-10 11:06:26 +01002281 if (global.tune.runqueue_depth <= 0) {
2282 /* tests on various thread counts from 1 to 64 have shown an
2283 * optimal queue depth following roughly 1/sqrt(threads).
2284 */
2285 int s = my_flsl(global.nbthread);
2286 s += (global.nbthread / s); // roughly twice the sqrt.
2287 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2288 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002289
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002290 if (global.tune.recv_enough == 0)
2291 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2292
Willy Tarreau27a674e2009-08-17 07:23:33 +02002293 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2294 global.tune.maxrewrite = global.tune.bufsize / 2;
2295
Willy Tarreaubaaee002006-06-26 02:48:02 +02002296 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2297 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002298 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002299 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2300 }
2301
William Lallemand095ba4c2017-06-01 17:38:50 +02002302 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002303 /* command line daemon mode inhibits foreground and debug modes mode */
2304 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002305 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002307
2308 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309
William Lallemand095ba4c2017-06-01 17:38:50 +02002310 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002311 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002312 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002313 }
2314
William Lallemand095ba4c2017-06-01 17:38:50 +02002315 if ((global.nbproc > 1) && !(global.mode & (MODE_DAEMON | MODE_MWORKER))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002316 if (!(global.mode & (MODE_FOREGROUND | MODE_DEBUG)))
Christopher Faulet767a84b2017-11-24 16:50:31 +01002317 ha_warning("<nbproc> is only meaningful in daemon mode or master-worker mode. Setting limit to 1 process.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002318 global.nbproc = 1;
2319 }
2320
2321 if (global.nbproc < 1)
2322 global.nbproc = 1;
2323
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002324 if (global.nbthread < 1)
2325 global.nbthread = 1;
2326
Christopher Faulet3ef26392017-08-29 16:46:57 +02002327 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002328 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002329 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002330 exit(1);
2331 }
2332
Christopher Faulet96d44832017-11-14 22:02:30 +01002333 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002334 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002335 exit(1);
2336 }
2337
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002338 /*
2339 * Note: we could register external pollers here.
2340 * Built-in pollers have been registered before main().
2341 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002342
Willy Tarreau43b78992009-01-25 15:42:27 +01002343 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002344 disable_poller("kqueue");
2345
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002346 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2347 disable_poller("evports");
2348
Willy Tarreau43b78992009-01-25 15:42:27 +01002349 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002350 disable_poller("epoll");
2351
Willy Tarreau43b78992009-01-25 15:42:27 +01002352 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002353 disable_poller("poll");
2354
Willy Tarreau43b78992009-01-25 15:42:27 +01002355 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002356 disable_poller("select");
2357
2358 /* Note: we could disable any poller by name here */
2359
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002360 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002361 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002362 fprintf(stderr, "\n");
2363 list_filters(stderr);
2364 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002365
Willy Tarreau4f60f162007-04-08 16:39:58 +02002366 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002367 ha_alert("No polling mechanism available.\n"
2368 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2369 " is too low on this platform to support maxconn and the number of listeners\n"
2370 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2371 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2372 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2373 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2374 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2375 " check build settings using 'haproxy -vv'.\n\n",
2376 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002377 exit(1);
2378 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002379 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2380 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002381 }
2382
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002383 if (!global.node)
2384 global.node = strdup(hostname);
2385
Willy Tarreau02b092f2020-10-07 18:36:54 +02002386 /* stop disabled proxies */
2387 for (px = proxies_list; px; px = px->next) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02002388 if (px->disabled)
Willy Tarreau02b092f2020-10-07 18:36:54 +02002389 stop_proxy(px);
2390 }
2391
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002392 if (!hlua_post_init())
2393 exit(1);
Thomas Holmes6abded42015-05-12 16:23:58 +01002394
Maxime de Roucy0f503922016-05-13 23:52:55 +02002395 free(err_msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002396}
2397
Simon Horman6fb82592011-07-15 13:14:11 +09002398static void deinit_acl_cond(struct acl_cond *cond)
Simon Hormanac821422011-07-15 13:14:09 +09002399{
Simon Hormanac821422011-07-15 13:14:09 +09002400 struct acl_term_suite *suite, *suiteb;
2401 struct acl_term *term, *termb;
2402
Simon Horman6fb82592011-07-15 13:14:11 +09002403 if (!cond)
2404 return;
2405
2406 list_for_each_entry_safe(suite, suiteb, &cond->suites, list) {
2407 list_for_each_entry_safe(term, termb, &suite->terms, list) {
2408 LIST_DEL(&term->list);
2409 free(term);
Simon Hormanac821422011-07-15 13:14:09 +09002410 }
Simon Horman6fb82592011-07-15 13:14:11 +09002411 LIST_DEL(&suite->list);
2412 free(suite);
2413 }
2414
2415 free(cond);
2416}
2417
Christopher Fauletcb550132019-12-17 11:25:46 +01002418static void deinit_act_rules(struct list *rules)
Simon Horman6fb82592011-07-15 13:14:11 +09002419{
Christopher Fauletcb550132019-12-17 11:25:46 +01002420 struct act_rule *rule, *ruleb;
Simon Horman6fb82592011-07-15 13:14:11 +09002421
Christopher Fauletcb550132019-12-17 11:25:46 +01002422 list_for_each_entry_safe(rule, ruleb, rules, list) {
2423 LIST_DEL(&rule->list);
2424 deinit_acl_cond(rule->cond);
Christopher Faulet58b35642019-12-17 11:48:42 +01002425 if (rule->release_ptr)
2426 rule->release_ptr(rule);
Christopher Fauletcb550132019-12-17 11:25:46 +01002427 free(rule);
Simon Hormanac821422011-07-15 13:14:09 +09002428 }
2429}
2430
Simon Horman6fb82592011-07-15 13:14:11 +09002431static void deinit_stick_rules(struct list *rules)
2432{
2433 struct sticking_rule *rule, *ruleb;
2434
2435 list_for_each_entry_safe(rule, ruleb, rules, list) {
2436 LIST_DEL(&rule->list);
2437 deinit_acl_cond(rule->cond);
Christopher Faulet476e5d02016-10-26 11:34:47 +02002438 release_sample_expr(rule->expr);
Simon Horman6fb82592011-07-15 13:14:11 +09002439 free(rule);
2440 }
2441}
2442
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002443void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002444{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002445 struct proxy *p = proxies_list, *p0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 struct cap_hdr *h,*h_next;
2447 struct server *s,*s_next;
2448 struct listener *l,*l_next;
Willy Tarreau0fc45a72007-06-17 00:36:03 +02002449 struct acl_cond *cond, *condb;
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002450 struct acl *acl, *aclb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002451 struct switching_rule *rule, *ruleb;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002452 struct server_rule *srule, *sruleb;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002453 struct redirect_rule *rdr, *rdrb;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002454 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002455 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002456 struct logsrv *log, *logb;
William Lallemand723b73a2012-02-08 16:37:49 +01002457 struct logformat_node *lf, *lfb;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002458 struct bind_conf *bind_conf, *bind_back;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002459 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002460 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002461 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002462 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002463 struct per_thread_init_fct *tif, *tifb;
2464 struct per_thread_deinit_fct *tdf, *tdfb;
2465 struct per_thread_alloc_fct *taf, *tafb;
2466 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002467 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002468 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002469 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002470 int cur_fd;
2471
2472 /* At this point the listeners state is weird:
2473 * - most listeners are still bound and referenced in their protocol
2474 * - some might be zombies that are not in their proto anymore, but
2475 * still appear in their proxy's listeners with a valid FD.
2476 * - some might be stopped and still appear in their proxy as FD #-1
2477 * - among all of them, some might be inherited hence shared and we're
2478 * not allowed to pause them or whatever, we must just close them.
2479 * - finally some are not listeners (pipes, logs, stdout, etc) and
2480 * must be left intact.
2481 *
2482 * The safe way to proceed is to unbind (and close) whatever is not yet
2483 * unbound so that no more receiver/listener remains alive. Then close
2484 * remaining listener FDs, which correspond to zombie listeners (those
2485 * belonging to disabled proxies that were in another process).
2486 * objt_listener() would be cleaner here but not converted yet.
2487 */
2488 protocol_unbind_all();
2489
2490 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002491 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002492 continue;
2493
Willy Tarreaua74cb382020-10-15 21:29:49 +02002494 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002495 struct listener *l = fdtab[cur_fd].owner;
2496
2497 BUG_ON(l->state != LI_INIT);
2498 unbind_listener(l);
2499 }
2500 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002501
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002502 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002503 while (p) {
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002504 free(p->conf.file);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002505 free(p->id);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002506 free(p->cookie_name);
2507 free(p->cookie_domain);
Christopher Faulet2f533902020-01-21 11:06:48 +01002508 free(p->cookie_attrs);
Willy Tarreau4c03d1c2019-01-14 15:23:54 +01002509 free(p->lbprm.arg_str);
Christopher Faulet3dab6c02021-02-12 09:28:13 +01002510 free(p->server_state_file_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002511 free(p->capture_name);
2512 free(p->monitor_uri);
Simon Hormana31c7f72011-07-15 13:14:08 +09002513 free(p->rdp_cookie_name);
William Lallemandefc5a9d2020-08-07 14:48:37 +02002514 free(p->invalid_rep);
2515 free(p->invalid_req);
Amaury Denoyelle7edf20e2021-01-26 14:35:22 +01002516#if defined(CONFIG_HAP_TRANSPARENT)
2517 free(p->conn_src.bind_hdr_name);
2518#endif
Willy Tarreau62a61232013-04-12 18:13:46 +02002519 if (p->conf.logformat_string != default_http_log_format &&
2520 p->conf.logformat_string != default_tcp_log_format &&
2521 p->conf.logformat_string != clf_http_log_format)
2522 free(p->conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002523
Willy Tarreau62a61232013-04-12 18:13:46 +02002524 free(p->conf.lfs_file);
2525 free(p->conf.uniqueid_format_string);
Tim Duesterhus18c63592020-07-04 11:49:42 +02002526 istfree(&p->header_unique_id);
Willy Tarreau62a61232013-04-12 18:13:46 +02002527 free(p->conf.uif_file);
Willy Tarreau0cac26c2019-01-14 16:55:42 +01002528 if ((p->lbprm.algo & BE_LB_LKUP) == BE_LB_LKUP_MAP)
2529 free(p->lbprm.map.srv);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002530
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002531 if (p->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2532 free(p->conf.logformat_sd_string);
2533 free(p->conf.lfsd_file);
2534
Willy Tarreaub80c2302007-11-30 20:51:32 +01002535 list_for_each_entry_safe(cond, condb, &p->mon_fail_cond, list) {
2536 LIST_DEL(&cond->list);
2537 prune_acl_cond(cond);
2538 free(cond);
2539 }
2540
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +02002541 EXTRA_COUNTERS_FREE(p->extra_counters_fe);
2542 EXTRA_COUNTERS_FREE(p->extra_counters_be);
2543
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002544 /* build a list of unique uri_auths */
2545 if (!ua)
2546 ua = p->uri_auth;
2547 else {
2548 /* check if p->uri_auth is unique */
2549 for (uap = ua; uap; uap=uap->next)
2550 if (uap == p->uri_auth)
2551 break;
2552
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002553 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002554 /* add it, if it is */
2555 p->uri_auth->next = ua;
2556 ua = p->uri_auth;
2557 }
2558 }
Willy Tarreau0fc45a72007-06-17 00:36:03 +02002559
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002560 list_for_each_entry_safe(acl, aclb, &p->acl, list) {
2561 LIST_DEL(&acl->list);
2562 prune_acl(acl);
2563 free(acl);
2564 }
2565
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002566 list_for_each_entry_safe(srule, sruleb, &p->server_rules, list) {
2567 LIST_DEL(&srule->list);
2568 prune_acl_cond(srule->cond);
Tim Duesterhus826cf072020-07-04 11:49:44 +02002569 list_for_each_entry_safe(lf, lfb, &srule->expr, list) {
2570 LIST_DEL(&lf->list);
2571 release_sample_expr(lf->expr);
2572 free(lf->arg);
2573 free(lf);
2574 }
Tim Duesterhus6fb74a12020-07-04 11:49:43 +02002575 free(srule->file);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02002576 free(srule->cond);
2577 free(srule);
2578 }
2579
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002580 list_for_each_entry_safe(rule, ruleb, &p->switching_rules, list) {
2581 LIST_DEL(&rule->list);
Willy Tarreauf51658d2014-04-23 01:21:56 +02002582 if (rule->cond) {
2583 prune_acl_cond(rule->cond);
2584 free(rule->cond);
2585 }
Dragan Dosen2a7c20f2019-04-30 00:38:36 +02002586 free(rule->file);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002587 free(rule);
2588 }
2589
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002590 list_for_each_entry_safe(rdr, rdrb, &p->redirect_rules, list) {
2591 LIST_DEL(&rdr->list);
Willy Tarreauf285f542010-01-03 20:03:03 +01002592 if (rdr->cond) {
2593 prune_acl_cond(rdr->cond);
2594 free(rdr->cond);
2595 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002596 free(rdr->rdr_str);
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01002597 list_for_each_entry_safe(lf, lfb, &rdr->rdr_fmt, list) {
2598 LIST_DEL(&lf->list);
2599 free(lf);
2600 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02002601 free(rdr);
2602 }
2603
William Lallemand0f99e342011-10-12 17:50:54 +02002604 list_for_each_entry_safe(log, logb, &p->logsrvs, list) {
2605 LIST_DEL(&log->list);
2606 free(log);
2607 }
2608
William Lallemand723b73a2012-02-08 16:37:49 +01002609 list_for_each_entry_safe(lf, lfb, &p->logformat, list) {
2610 LIST_DEL(&lf->list);
Dragan Dosen61302da2019-04-30 00:40:02 +02002611 release_sample_expr(lf->expr);
2612 free(lf->arg);
William Lallemand723b73a2012-02-08 16:37:49 +01002613 free(lf);
2614 }
2615
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002616 list_for_each_entry_safe(lf, lfb, &p->logformat_sd, list) {
2617 LIST_DEL(&lf->list);
Dragan Dosen61302da2019-04-30 00:40:02 +02002618 release_sample_expr(lf->expr);
2619 free(lf->arg);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002620 free(lf);
2621 }
2622
Tim Duesterhus79765782020-07-04 11:49:40 +02002623 list_for_each_entry_safe(lf, lfb, &p->format_unique_id, list) {
2624 LIST_DEL(&lf->list);
2625 release_sample_expr(lf->expr);
2626 free(lf->arg);
2627 free(lf);
2628 }
2629
Christopher Fauletcb550132019-12-17 11:25:46 +01002630 deinit_act_rules(&p->tcp_req.inspect_rules);
2631 deinit_act_rules(&p->tcp_rep.inspect_rules);
2632 deinit_act_rules(&p->tcp_req.l4_rules);
2633 deinit_act_rules(&p->tcp_req.l5_rules);
2634 deinit_act_rules(&p->http_req_rules);
2635 deinit_act_rules(&p->http_res_rules);
Christopher Faulet6d0c3df2020-01-22 09:26:35 +01002636 deinit_act_rules(&p->http_after_res_rules);
Simon Hormanac821422011-07-15 13:14:09 +09002637
Simon Horman6fb82592011-07-15 13:14:11 +09002638 deinit_stick_rules(&p->storersp_rules);
2639 deinit_stick_rules(&p->sticking_rules);
2640
Willy Tarreaubaaee002006-06-26 02:48:02 +02002641 h = p->req_cap;
2642 while (h) {
2643 h_next = h->next;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002644 free(h->name);
Willy Tarreaubafbe012017-11-24 17:34:44 +01002645 pool_destroy(h->pool);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 free(h);
2647 h = h_next;
2648 }/* end while(h) */
2649
2650 h = p->rsp_cap;
2651 while (h) {
2652 h_next = h->next;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002653 free(h->name);
Willy Tarreaubafbe012017-11-24 17:34:44 +01002654 pool_destroy(h->pool);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655 free(h);
2656 h = h_next;
2657 }/* end while(h) */
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002658
Willy Tarreaubaaee002006-06-26 02:48:02 +02002659 s = p->srv;
2660 while (s) {
2661 s_next = s->next;
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002662
Dragan Dosen026ef572019-04-30 00:56:20 +02002663
Willy Tarreauf6562792019-05-07 19:05:35 +02002664 task_destroy(s->warmup);
Christopher Faulet25fbca42021-06-15 16:17:17 +02002665 task_destroy(s->srvrq_check);
Willy Tarreau2e993902011-10-31 11:53:20 +01002666
Willy Tarreaua534fea2008-08-03 12:19:50 +02002667 free(s->id);
2668 free(s->cookie);
Tim Duesterhuscb8f13c2020-07-04 11:49:41 +02002669 free(s->hostname);
Christopher Faulet67957bd2017-09-27 11:00:59 +02002670 free(s->hostname_dn);
Sárközi, László34c01792014-09-05 10:08:23 +02002671 free((char*)s->conf.file);
Olivier Houchard7fc3be72018-11-22 18:50:54 +01002672 free(s->idle_conns);
Olivier Houchard7fc3be72018-11-22 18:50:54 +01002673 free(s->safe_conns);
Olivier Houcharddc2f2752020-02-13 19:12:07 +01002674 free(s->available_conns);
Olivier Houchardf1314812019-02-18 16:41:17 +01002675 free(s->curr_idle_thr);
Tim Duesterhuscb8f13c2020-07-04 11:49:41 +02002676 free(s->resolvers_id);
Amaury Denoyelle2bf658c2021-04-20 16:48:22 +02002677 free(s->lb_nodes);
Willy Tarreau17d45382016-12-22 21:16:08 +01002678
Christopher Fauletf61f33a2020-03-27 18:55:49 +01002679 if (s->use_ssl == 1 || s->check.use_ssl == 1 || (s->proxy->options & PR_O_TCPCHK_SSL)) {
Willy Tarreau17d45382016-12-22 21:16:08 +01002680 if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->destroy_srv)
2681 xprt_get(XPRT_SSL)->destroy_srv(s);
2682 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01002683 HA_SPIN_DESTROY(&s->lock);
Christopher Faulet3ea5cbe2019-07-31 08:44:12 +02002684
2685 list_for_each_entry(srvdf, &server_deinit_list, list)
2686 srvdf->fct(s);
2687
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +02002688 EXTRA_COUNTERS_FREE(s->extra_counters);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 free(s);
2690 s = s_next;
2691 }/* end while(s) */
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002692
Willy Tarreau4348fad2012-09-20 16:48:07 +02002693 list_for_each_entry_safe(l, l_next, &p->conf.listeners, by_fe) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002694 LIST_DEL(&l->by_fe);
2695 LIST_DEL(&l->by_bind);
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01002696 free(l->name);
2697 free(l->counters);
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +02002698
2699 EXTRA_COUNTERS_FREE(l->extra_counters);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 free(l);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002701 }
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002702
Willy Tarreau4348fad2012-09-20 16:48:07 +02002703 /* Release unused SSL configs. */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002704 list_for_each_entry_safe(bind_conf, bind_back, &p->conf.bind, by_fe) {
Willy Tarreau795cdab2016-12-22 17:30:54 +01002705 if (bind_conf->xprt->destroy_bind_conf)
2706 bind_conf->xprt->destroy_bind_conf(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002707 free(bind_conf->file);
2708 free(bind_conf->arg);
2709 LIST_DEL(&bind_conf->by_fe);
2710 free(bind_conf);
2711 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02002712
Christopher Fauletd7c91962015-04-30 11:48:27 +02002713 flt_deinit(p);
2714
Christopher Faulet3ea5cbe2019-07-31 08:44:12 +02002715 list_for_each_entry(pxdf, &proxy_deinit_list, list)
2716 pxdf->fct(p);
2717
Krzysztof Piotr Oledzkiaff01ea2010-02-05 20:31:44 +01002718 free(p->desc);
2719 free(p->fwdfor_hdr_name);
2720
Olivier Houchard3f795f72019-04-17 22:51:06 +02002721 task_destroy(p->task);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002722
Willy Tarreaubafbe012017-11-24 17:34:44 +01002723 pool_destroy(p->req_cap_pool);
2724 pool_destroy(p->rsp_cap_pool);
Dragan Dosen7d61a332019-05-07 14:16:18 +02002725 if (p->table)
2726 pool_destroy(p->table->pool);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002727
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002728 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729 p = p->next;
Willy Tarreaucd10def2020-10-17 18:48:47 +02002730 HA_RWLOCK_DESTROY(&p0->lbprm.lock);
Willy Tarreauac66d6b2020-10-20 17:24:27 +02002731 HA_RWLOCK_DESTROY(&p0->lock);
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002732 free(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002733 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002734
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002735 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002736 struct stat_scope *scope, *scopep;
2737
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002738 uap = ua;
2739 ua = ua->next;
2740
Willy Tarreaua534fea2008-08-03 12:19:50 +02002741 free(uap->uri_prefix);
2742 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002743 free(uap->node);
2744 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002745
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002746 userlist_free(uap->userlist);
Christopher Fauletcb550132019-12-17 11:25:46 +01002747 deinit_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002748
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002749 scope = uap->scope;
2750 while (scope) {
2751 scopep = scope;
2752 scope = scope->next;
2753
2754 free(scopep->px_id);
2755 free(scopep);
2756 }
2757
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002758 free(uap);
2759 }
2760
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002761 userlist_free(userlist);
2762
David Carlier834cb2e2015-09-25 12:02:25 +01002763 cfg_unregister_sections();
2764
Christopher Faulet0132d062017-07-26 15:33:35 +02002765 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002766
Willy Tarreau05554e62016-12-21 20:46:26 +01002767 list_for_each_entry(pdf, &post_deinit_list, list)
2768 pdf->fct();
2769
Joe Williamsdf5b38f2010-12-29 17:05:48 +01002770 free(global.log_send_hostname); global.log_send_hostname = NULL;
Dragan Dosen43885c72015-10-01 13:18:13 +02002771 chunk_destroy(&global.log_tag);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002772 free(global.chroot); global.chroot = NULL;
2773 free(global.pidfile); global.pidfile = NULL;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002774 free(global.node); global.node = NULL;
2775 free(global.desc); global.desc = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002776 free(oldpids); oldpids = NULL;
Tim Duesterhus9e0c2f32020-09-10 19:46:39 +02002777 free(old_argv); old_argv = NULL;
Dragan Dosen4f014152020-06-18 16:56:47 +02002778 free(localpeer); localpeer = NULL;
Christopher Faulet3dab6c02021-02-12 09:28:13 +01002779 free(global.server_state_base); global.server_state_base = NULL;
2780 free(global.server_state_file); global.server_state_file = NULL;
Olivier Houchard3f795f72019-04-17 22:51:06 +02002781 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002782 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002783
William Lallemand0f99e342011-10-12 17:50:54 +02002784 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
2785 LIST_DEL(&log->list);
2786 free(log);
2787 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002788 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002789 free(wl->s);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002790 LIST_DEL(&wl->list);
2791 free(wl);
2792 }
2793
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002794 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2795 if (bol->must_free)
2796 free((void *)bol->str);
2797 LIST_DEL(&bol->list);
2798 free(bol);
2799 }
2800
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002801 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
2802 LIST_DEL(&pxdf->list);
2803 free(pxdf);
2804 }
2805
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002806 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
2807 LIST_DEL(&pdf->list);
2808 free(pdf);
2809 }
2810
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002811 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
2812 LIST_DEL(&srvdf->list);
2813 free(srvdf);
2814 }
2815
Tim Duesterhusfc854942020-09-10 19:46:42 +02002816 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
2817 LIST_DEL(&pcf->list);
2818 free(pcf);
2819 }
2820
Tim Duesterhus34bef072020-07-04 11:49:50 +02002821 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
2822 LIST_DEL(&pscf->list);
2823 free(pscf);
2824 }
2825
Tim Duesterhus53508d62020-09-10 19:46:40 +02002826 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
2827 LIST_DEL(&ppcf->list);
2828 free(ppcf);
2829 }
2830
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002831 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
2832 LIST_DEL(&tif->list);
2833 free(tif);
2834 }
2835
2836 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
2837 LIST_DEL(&tdf->list);
2838 free(tdf);
2839 }
2840
2841 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
2842 LIST_DEL(&taf->list);
2843 free(taf);
2844 }
2845
2846 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
2847 LIST_DEL(&tff->list);
2848 free(tff);
2849 }
2850
Christopher Fauletff2613e2016-11-09 11:36:17 +01002851 vars_prune(&global.vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002852 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002853 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854} /* end deinit() */
2855
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002856__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002857{
2858 deinit();
2859 exit(status);
2860}
William Lallemand72160322018-11-06 17:37:16 +01002861
Willy Tarreau918ff602011-07-25 16:33:49 +02002862/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002863void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002864{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002865 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002866
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002867 tv_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002868 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002869 wake_expired_tasks();
2870
William Lallemand1aab50b2018-06-07 09:46:01 +02002871 /* check if we caught some signals and process them in the
2872 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002873 if (signal_queue_len && tid == 0) {
2874 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002875 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002876 }
2877
2878 /* Process a few tasks */
2879 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002880
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002881 /* also stop if we failed to cleanly stop all tasks */
2882 if (killed > 1)
2883 break;
2884
Willy Tarreau10146c92015-04-13 20:44:19 +02002885 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002886 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002887 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002888 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002889 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002890 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2891 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002892 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002893 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002894 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002895 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002896 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002897 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002898
Willy Tarreau4f46a352020-03-23 09:27:28 +01002899 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002900 int i;
2901
2902 if (stopping) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002903 if (_HA_ATOMIC_OR(&stopping_thread_mask, tid_bit) == tid_bit) {
2904 /* notify all threads that stopping was just set */
2905 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002906 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002907 wake_thread(i);
2908 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002909 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002910
2911 /* stop when there's nothing left to do */
2912 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002913 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2914 /* wake all threads waiting on jobs==0 */
2915 for (i = 0; i < global.nbthread; i++)
2916 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2917 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002918 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002919 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002920 }
2921
Willy Tarreauc49ba522019-12-11 08:12:23 +01002922 /* If we have to sleep, measure how long */
2923 next = wake ? TICK_ETERNITY : next_timer_expiry();
2924
Willy Tarreau58b458d2008-06-29 22:40:23 +02002925 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002926 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002927
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002928 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002929 }
2930}
2931
Christopher Faulet1d17c102017-08-29 15:38:48 +02002932static void *run_thread_poll_loop(void *data)
2933{
Willy Tarreau082b6282019-05-22 14:42:12 +02002934 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002935 struct per_thread_init_fct *ptif;
2936 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002937 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002938 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002939 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2940 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002941
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02002942 ha_set_tid((unsigned long)data);
Willy Tarreaud022e9c2019-09-24 08:25:15 +02002943 sched = &task_per_thread[tid];
Willy Tarreau91e6df02019-05-03 17:21:18 +02002944
Willy Tarreauf6178242019-05-21 19:46:58 +02002945#if (_POSIX_TIMERS > 0) && defined(_POSIX_THREAD_CPUTIME)
Willy Tarreau91e6df02019-05-03 17:21:18 +02002946#ifdef USE_THREAD
Willy Tarreau8323a372019-05-20 18:57:53 +02002947 pthread_getcpuclockid(pthread_self(), &ti->clock_id);
Willy Tarreau624dcbf2019-05-20 20:23:06 +02002948#else
Willy Tarreau8323a372019-05-20 18:57:53 +02002949 ti->clock_id = CLOCK_THREAD_CPUTIME_ID;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002950#endif
Willy Tarreau663fda42019-05-21 15:14:08 +02002951#endif
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002952 /* Now, initialize one thread init at a time. This is better since
2953 * some init code is a bit tricky and may release global resources
2954 * after reallocating them locally. This will also ensure there is
2955 * no race on file descriptors allocation.
2956 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002957#ifdef USE_THREAD
2958 pthread_mutex_lock(&init_mutex);
2959#endif
2960 /* The first thread must set the number of threads left */
2961 if (!init_left)
2962 init_left = global.nbthread;
2963 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002964
Christopher Faulet1d17c102017-08-29 15:38:48 +02002965 tv_update_date(-1,-1);
2966
Willy Tarreau082b6282019-05-22 14:42:12 +02002967 /* per-thread alloc calls performed here are not allowed to snoop on
2968 * other threads, so they are free to initialize at their own rhythm
2969 * as long as they act as if they were alone. None of them may rely
2970 * on resources initialized by the other ones.
2971 */
2972 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2973 if (!ptaf->fct()) {
2974 ha_alert("failed to allocate resources for thread %u.\n", tid);
2975 exit(1);
2976 }
2977 }
2978
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002979 /* per-thread init calls performed here are not allowed to snoop on
2980 * other threads, so they are free to initialize at their own rhythm
2981 * as long as they act as if they were alone.
2982 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002983 list_for_each_entry(ptif, &per_thread_init_list, list) {
2984 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002985 ha_alert("failed to initialize thread %u.\n", tid);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002986 exit(1);
2987 }
2988 }
2989
Willy Tarreau71092822019-06-10 09:51:04 +02002990 /* enabling protocols will result in fd_insert() calls to be performed,
2991 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002992 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002993 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002994 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002995 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002996
Willy Tarreau34a150c2019-06-11 09:16:41 +02002997#ifdef USE_THREAD
2998 pthread_cond_broadcast(&init_cond);
2999 pthread_mutex_unlock(&init_mutex);
3000
3001 /* now wait for other threads to finish starting */
3002 pthread_mutex_lock(&init_mutex);
3003 while (init_left)
3004 pthread_cond_wait(&init_cond, &init_mutex);
3005 pthread_mutex_unlock(&init_mutex);
3006#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02003007
Willy Tarreaua45a8b52019-12-06 16:31:45 +01003008#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
3009 /* Let's refrain from using setuid executables. This way the impact of
3010 * an eventual vulnerability in a library remains limited. It may
3011 * impact external checks but who cares about them anyway ? In the
3012 * worst case it's possible to disable the option. Obviously we do this
3013 * in workers only. We can't hard-fail on this one as it really is
3014 * implementation dependent though we're interested in feedback, hence
3015 * the warning.
3016 */
3017 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
3018 static int warn_fail;
3019 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1 && !_HA_ATOMIC_XADD(&warn_fail, 1)) {
3020 ha_warning("Failed to disable setuid, please report to developers with detailed "
3021 "information about your operating system. You can silence this warning "
3022 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
3023 }
3024 }
3025#endif
3026
Willy Tarreaud96f1122019-12-03 07:07:36 +01003027#if defined(RLIMIT_NPROC)
3028 /* all threads have started, it's now time to prevent any new thread
3029 * or process from starting. Obviously we do this in workers only. We
3030 * can't hard-fail on this one as it really is implementation dependent
3031 * though we're interested in feedback, hence the warning.
3032 */
3033 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
3034 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
3035 static int warn_fail;
3036
3037 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_XADD(&warn_fail, 1)) {
3038 ha_warning("Failed to disable forks, please report to developers with detailed "
3039 "information about your operating system. You can silence this warning "
3040 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
3041 }
3042 }
3043#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003044 run_poll_loop();
3045
3046 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
3047 ptdf->fct();
3048
Willy Tarreau082b6282019-05-22 14:42:12 +02003049 list_for_each_entry(ptff, &per_thread_free_list, list)
3050 ptff->fct();
3051
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003052#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01003053 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003054 if (tid > 0)
3055 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003056#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003057 return NULL;
3058}
Christopher Faulet1d17c102017-08-29 15:38:48 +02003059
William Dauchyf9af9d72019-11-17 15:47:16 +01003060/* set uid/gid depending on global settings */
3061static void set_identity(const char *program_name)
3062{
3063 if (global.gid) {
3064 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
3065 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
3066 " without 'uid'/'user' is generally useless.\n", program_name);
3067
3068 if (setgid(global.gid) == -1) {
3069 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
3070 protocol_unbind_all();
3071 exit(1);
3072 }
3073 }
3074
3075 if (global.uid && setuid(global.uid) == -1) {
3076 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
3077 protocol_unbind_all();
3078 exit(1);
3079 }
3080}
3081
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082int main(int argc, char **argv)
3083{
3084 int err, retry;
3085 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02003086 int pidfd = -1;
Willy Tarreau228cbaf2021-07-14 17:54:01 +02003087 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
3088
3089 /* Catch forced CFLAGS that miss 2-complement integer overflow */
3090 if (intovf + 0x7FFFFFFF >= intovf) {
3091 fprintf(stderr,
3092 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
3093 "The source code was miscompiled by the compiler, which usually indicates that\n"
3094 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
3095 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
3096 "and INSTALL files to decide on the best way to pass your local build options.\n"
3097 "\nBuild options :"
3098#ifdef BUILD_TARGET
3099 "\n TARGET = " BUILD_TARGET
3100#endif
3101#ifdef BUILD_CPU
3102 "\n CPU = " BUILD_CPU
3103#endif
3104#ifdef BUILD_CC
3105 "\n CC = " BUILD_CC
3106#endif
3107#ifdef BUILD_CFLAGS
3108 "\n CFLAGS = " BUILD_CFLAGS
3109#endif
3110#ifdef BUILD_OPTIONS
3111 "\n OPTIONS = " BUILD_OPTIONS
3112#endif
3113#ifdef BUILD_DEBUG
3114 "\n DEBUG = " BUILD_DEBUG
3115#endif
3116 "\n\n");
3117 return 1;
3118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119
Olivier Houchard5fa300d2018-02-03 15:15:21 +01003120 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003121
Willy Tarreauff9c9142019-02-07 10:39:36 +01003122 /* this can only safely be done here, though it's optimized away by
3123 * the compiler.
3124 */
3125 if (MAX_PROCS < 1 || MAX_PROCS > LONGBITS) {
3126 ha_alert("MAX_PROCS value must be between 1 and %d inclusive; "
3127 "HAProxy was built with value %d, please fix it and rebuild.\n",
3128 LONGBITS, MAX_PROCS);
3129 exit(1);
3130 }
3131
Willy Tarreaubf696402019-03-01 10:09:28 +01003132 /* take a copy of initial limits before we possibly change them */
3133 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02003134
3135 if (limit.rlim_max == RLIM_INFINITY)
3136 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01003137 rlim_fd_cur_at_boot = limit.rlim_cur;
3138 rlim_fd_max_at_boot = limit.rlim_max;
3139
Willy Tarreau5794fb02018-11-25 18:43:29 +01003140 /* process all initcalls in order of potential dependency */
3141 RUN_INITCALLS(STG_PREPARE);
3142 RUN_INITCALLS(STG_LOCK);
3143 RUN_INITCALLS(STG_ALLOC);
3144 RUN_INITCALLS(STG_POOL);
3145 RUN_INITCALLS(STG_REGISTER);
3146 RUN_INITCALLS(STG_INIT);
3147
Emeric Bruncf20bf12010-10-22 16:06:11 +02003148 init(argc, argv);
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003149 signal_register_fct(SIGQUIT, dump, SIGQUIT);
3150 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
3151 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02003152 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153
Willy Tarreaue437c442010-03-17 18:02:46 +01003154 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
3155 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
3156 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003157 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003158 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159
Willy Tarreaudc23a922011-02-16 11:10:36 +01003160 /* ulimits */
3161 if (!global.rlimit_nofile)
3162 global.rlimit_nofile = global.maxsock;
3163
3164 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01003165 limit.rlim_cur = global.rlimit_nofile;
3166 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
3167
Willy Tarreaudc23a922011-02-16 11:10:36 +01003168 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02003169 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003170 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3171 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
3172 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin4b1148f2021-01-12 20:19:38 +01003173 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003174 }
3175 else {
3176 /* try to set it to the max possible at least */
3177 limit.rlim_cur = limit.rlim_max;
3178 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
3179 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02003180
William Dauchya5194602020-03-28 19:29:58 +01003181 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003182 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
3183 global.rlimit_nofile = limit.rlim_cur;
3184 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01003185 }
3186 }
3187
3188 if (global.rlimit_memmax) {
3189 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01003190 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01003191#ifdef RLIMIT_AS
3192 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003193 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3194 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3195 argv[0], global.rlimit_memmax);
Jerome Magnin4b1148f2021-01-12 20:19:38 +01003196 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003197 }
3198 else
William Dauchya5194602020-03-28 19:29:58 +01003199 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003200 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003201 }
3202#else
3203 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003204 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3205 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3206 argv[0], global.rlimit_memmax);
Jerome Magnin4b1148f2021-01-12 20:19:38 +01003207 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003208 }
3209 else
William Dauchya5194602020-03-28 19:29:58 +01003210 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003211 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003212 }
3213#endif
3214 }
3215
Olivier Houchardf73629d2017-04-05 22:33:04 +02003216 if (old_unixsocket) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003217 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003218 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003219 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003220 if (!(global.mode & MODE_MWORKER))
3221 exit(1);
3222 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003223 }
3224 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003225 get_cur_unixsocket();
3226
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 /* We will loop at most 100 times with 10 ms delay each time.
3228 * That's at most 1 second. We only send a signal to old pids
3229 * if we cannot grab at least one port.
3230 */
3231 retry = MAX_START_RETRIES;
3232 err = ERR_NONE;
3233 while (retry >= 0) {
3234 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003235 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003236 /* exit the loop on no error or fatal error */
3237 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003238 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003239 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 break;
3241
3242 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3243 * listening sockets. So on those platforms, it would be wiser to
3244 * simply send SIGUSR1, which will not be undoable.
3245 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003246 if (tell_old_pids(SIGTTOU) == 0) {
3247 /* no need to wait if we can't contact old pids */
3248 retry = 0;
3249 continue;
3250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 /* give some time to old processes to stop listening */
3252 w.tv_sec = 0;
3253 w.tv_usec = 10*1000;
3254 select(0, NULL, NULL, NULL, &w);
3255 retry--;
3256 }
3257
Willy Tarreaue91bff22020-09-02 11:11:43 +02003258 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003259 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003260 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003261 if (retry != MAX_START_RETRIES && nb_oldpids) {
3262 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 exit(1);
3266 }
3267
William Lallemand944e6192018-11-21 15:48:31 +01003268 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003269 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 /* Note: we don't have to send anything to the old pids because we
3271 * never stopped them. */
3272 exit(1);
3273 }
3274
Willy Tarreaue91bff22020-09-02 11:11:43 +02003275 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003276 * the previous process gave us, we don't need them anymore
3277 */
3278 while (xfer_sock_list != NULL) {
3279 struct xfer_sock_list *tmpxfer = xfer_sock_list->next;
3280 close(xfer_sock_list->fd);
3281 free(xfer_sock_list->iface);
3282 free(xfer_sock_list->namespace);
3283 free(xfer_sock_list);
3284 xfer_sock_list = tmpxfer;
3285 }
Willy Tarreaudd815982007-10-16 12:25:14 +02003286
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003288 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3289 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290
Willy Tarreaubaaee002006-06-26 02:48:02 +02003291 /* MODE_QUIET can inhibit alerts and warnings below this line */
3292
PiBa-NL149a81a2017-12-25 21:03:31 +01003293 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3294 /* either stdin/out/err are already closed or should stay as they are. */
3295 if ((global.mode & MODE_DAEMON)) {
3296 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3297 global.mode &= ~MODE_VERBOSE;
3298 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3299 }
3300 } else {
3301 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3302 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003303 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003304 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 }
3306
3307 /* open log & pid files before the chroot */
William Lallemand80293002017-11-06 11:00:03 +01003308 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 unlink(global.pidfile);
3310 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3311 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003312 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313 if (nb_oldpids)
3314 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003315 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 exit(1);
3317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 }
3319
Willy Tarreaub38651a2007-03-24 17:24:39 +01003320 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003321 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3322 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003323 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003324 exit(1);
3325 }
3326
Jackie Tapia749f74c2020-07-22 18:59:40 -05003327 /* If the user is not root, we'll still let them try the configuration
3328 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003329 */
3330 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003331 ha_warning("[%s.main()] Some options which require full privileges"
3332 " might not work well.\n"
3333 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003334
William Lallemand095ba4c2017-06-01 17:38:50 +02003335 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3336
3337 /* chroot if needed */
3338 if (global.chroot != NULL) {
3339 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003340 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003341 if (nb_oldpids)
3342 tell_old_pids(SIGTTIN);
3343 protocol_unbind_all();
3344 exit(1);
3345 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003346 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003347 }
3348
William Lallemand944e6192018-11-21 15:48:31 +01003349 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003350 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351
William Lallemand27edc4b2019-05-07 17:49:33 +02003352 /* send a SIGTERM to workers who have a too high reloads number */
3353 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3354 mworker_kill_max_reloads(SIGTERM);
3355
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 /* Note that any error at this stage will be fatal because we will not
3357 * be able to restart the old pids.
3358 */
3359
William Dauchyf9af9d72019-11-17 15:47:16 +01003360 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3361 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003362
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 /* check ulimits */
3364 limit.rlim_cur = limit.rlim_max = 0;
3365 getrlimit(RLIMIT_NOFILE, &limit);
3366 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003367 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3368 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3369 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3370 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3371 global.maxsock);
Jerome Magnin4b1148f2021-01-12 20:19:38 +01003372 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003373 }
3374 else
3375 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003376 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003377 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3378 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 }
3380
William Lallemand944e6192018-11-21 15:48:31 +01003381 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003382 struct proxy *px;
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003383 struct peers *curpeers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 int ret = 0;
3385 int proc;
William Lallemande1340412017-12-28 16:09:36 +01003386 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003387
William Lallemand095ba4c2017-06-01 17:38:50 +02003388 /*
3389 * if daemon + mworker: must fork here to let a master
3390 * process live in background before forking children
3391 */
William Lallemand73b85e72017-06-01 17:38:51 +02003392
3393 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3394 && (global.mode & MODE_MWORKER)
3395 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003396 ret = fork();
3397 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003398 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003399 protocol_unbind_all();
3400 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003401 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003402 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003403 } else /* change the process group ID in the child (master process) */
3404 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003405 }
William Lallemande20b6a62017-06-01 17:38:55 +02003406
William Lallemande20b6a62017-06-01 17:38:55 +02003407
William Lallemanddeed7802017-11-06 11:00:04 +01003408 /* if in master-worker mode, write the PID of the father */
3409 if (global.mode & MODE_MWORKER) {
3410 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003411 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003412 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003413 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003414 }
3415
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003417 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003418 if (global.mode & MODE_MWORKER)
3419 mworker_ext_launch_all();
William Lallemand944e6192018-11-21 15:48:31 +01003420 for (proc = 0; proc < global.nbproc; proc++) {
3421 ret = fork();
3422 if (ret < 0) {
3423 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3424 protocol_unbind_all();
3425 exit(1); /* there has been an error */
3426 }
Willy Tarreau52bf8392020-03-08 00:42:37 +01003427 else if (ret == 0) { /* child breaks here */
3428 ha_random_jump96(relative_pid);
William Lallemand944e6192018-11-21 15:48:31 +01003429 break;
Willy Tarreau52bf8392020-03-08 00:42:37 +01003430 }
William Lallemand944e6192018-11-21 15:48:31 +01003431 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3432 char pidstr[100];
3433 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003434 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003435 }
3436 if (global.mode & MODE_MWORKER) {
3437 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003438
William Lallemand220567e2018-11-21 18:04:53 +01003439 ha_notice("New worker #%d (%d) forked\n", relative_pid, ret);
William Lallemand944e6192018-11-21 15:48:31 +01003440 /* find the right mworker_proc */
3441 list_for_each_entry(child, &proc_list, list) {
3442 if (child->relative_pid == relative_pid &&
William Lallemand8f7069a2019-04-12 16:09:23 +02003443 child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003444 child->timestamp = now.tv_sec;
3445 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003446 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003447 break;
3448 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003449 }
3450 }
William Lallemandbc193052018-09-11 10:06:26 +02003451
William Lallemand944e6192018-11-21 15:48:31 +01003452 relative_pid++; /* each child will get a different one */
3453 pid_bit <<= 1;
3454 }
3455 } else {
3456 /* wait mode */
3457 global.nbproc = 1;
3458 proc = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003459 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003460
3461#ifdef USE_CPU_AFFINITY
3462 if (proc < global.nbproc && /* child */
Willy Tarreauff9c9142019-02-07 10:39:36 +01003463 proc < MAX_PROCS && /* only the first 32/64 processes may be pinned */
Christopher Fauletcb6a9452017-11-22 16:50:41 +01003464 global.cpu_map.proc[proc]) /* only do this if the process has a CPU map */
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003465#ifdef __FreeBSD__
Olivier Houchard97148f62017-08-16 17:29:11 +02003466 {
3467 cpuset_t cpuset;
3468 int i;
Christopher Fauletcb6a9452017-11-22 16:50:41 +01003469 unsigned long cpu_map = global.cpu_map.proc[proc];
Olivier Houchard97148f62017-08-16 17:29:11 +02003470
3471 CPU_ZERO(&cpuset);
3472 while ((i = ffsl(cpu_map)) > 0) {
3473 CPU_SET(i - 1, &cpuset);
Cyril Bontéd400ab32018-03-12 21:47:39 +01003474 cpu_map &= ~(1UL << (i - 1));
Olivier Houchard97148f62017-08-16 17:29:11 +02003475 }
3476 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(cpuset), &cpuset);
3477 }
David Carlierc5ab3f02020-12-02 21:14:51 +00003478#elif defined(__linux__) || defined(__DragonFly__)
Christopher Fauletcb6a9452017-11-22 16:50:41 +01003479 sched_setaffinity(0, sizeof(unsigned long), (void *)&global.cpu_map.proc[proc]);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003480#endif
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003481#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003482 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003483 if (pidfd >= 0) {
3484 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3485 close(pidfd);
3486 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003487
3488 /* We won't ever use this anymore */
Willy Tarreaud137dd32010-08-25 12:49:05 +02003489 free(global.pidfile); global.pidfile = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003490
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003491 if (proc == global.nbproc) {
William Lallemand944e6192018-11-21 15:48:31 +01003492 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003493
3494 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3495 (global.mode & MODE_DAEMON)) {
3496 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003497 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3498 stdio_quiet(-1);
3499
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003500 global.mode &= ~MODE_VERBOSE;
3501 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003502 }
3503
William Lallemandb3f2be32018-09-11 10:06:18 +02003504 mworker_loop();
William Lallemand1499b9b2017-06-07 15:04:47 +02003505 /* should never get there */
3506 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003507 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003508#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003509 ssl_free_dh();
3510#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003511 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003512 }
3513
William Lallemandcb11fd22017-06-01 17:38:52 +02003514 /* child must never use the atexit function */
3515 atexit_flag = 0;
3516
William Lallemandbc193052018-09-11 10:06:26 +02003517 /* close useless master sockets */
3518 if (global.mode & MODE_MWORKER) {
3519 struct mworker_proc *child, *it;
3520 master = 0;
3521
William Lallemand309dc9a2018-10-26 14:47:45 +02003522 mworker_cli_proxy_stop();
3523
William Lallemandbc193052018-09-11 10:06:26 +02003524 /* free proc struct of other processes */
3525 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003526 /* close the FD of the master side for all
3527 * workers, we don't need to close the worker
3528 * side of other workers since it's done with
3529 * the bind_proc */
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003530 if (child->ipc_fd[0] >= 0)
3531 close(child->ipc_fd[0]);
William Lallemandce83b4a2018-10-26 14:47:30 +02003532 if (child->relative_pid == relative_pid &&
3533 child->reloads == 0) {
3534 /* keep this struct if this is our pid */
3535 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003536 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003537 }
William Lallemandbc193052018-09-11 10:06:26 +02003538 LIST_DEL(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003539 mworker_free_child(child);
3540 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003541 }
3542 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003543
William Lallemande1340412017-12-28 16:09:36 +01003544 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3545 devnullfd = open("/dev/null", O_RDWR, 0);
3546 if (devnullfd < 0) {
3547 ha_alert("Cannot open /dev/null\n");
3548 exit(EXIT_FAILURE);
3549 }
3550 }
3551
William Lallemand095ba4c2017-06-01 17:38:50 +02003552 /* Must chroot and setgid/setuid in the children */
3553 /* chroot if needed */
3554 if (global.chroot != NULL) {
3555 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreau4d15f1b2021-06-15 08:59:19 +02003556 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003557 if (nb_oldpids)
3558 tell_old_pids(SIGTTIN);
3559 protocol_unbind_all();
3560 exit(1);
3561 }
3562 }
3563
3564 free(global.chroot);
3565 global.chroot = NULL;
William Dauchyf9af9d72019-11-17 15:47:16 +01003566 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003567
William Lallemand7f80eb22017-05-26 18:19:55 +02003568 /* pass through every cli socket, and check if it's bound to
3569 * the current process and if it exposes listeners sockets.
3570 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3571 * */
3572
3573 if (global.stats_fe) {
3574 struct bind_conf *bind_conf;
3575
3576 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
3577 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreaue26993c2020-09-03 07:18:55 +02003578 if (!bind_conf->settings.bind_proc || bind_conf->settings.bind_proc & (1UL << proc)) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003579 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3580 break;
3581 }
3582 }
3583 }
3584 }
3585
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003586 /* we might have to unbind some proxies from some processes */
Olivier Houchardfbc74e82017-11-24 16:54:05 +01003587 px = proxies_list;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003588 while (px != NULL) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02003589 if (px->bind_proc && !px->disabled) {
Willy Tarreau337c8352020-09-24 10:51:29 +02003590 if (!(px->bind_proc & (1UL << proc)))
3591 stop_proxy(px);
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003592 }
3593 px = px->next;
3594 }
3595
Emeric Brunc47ba592020-10-07 10:13:10 +02003596 /* we might have to unbind some log forward proxies from some processes */
3597 px = cfg_log_forward;
3598 while (px != NULL) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02003599 if (px->bind_proc && !px->disabled) {
Willy Tarreau337c8352020-09-24 10:51:29 +02003600 if (!(px->bind_proc & (1UL << proc)))
3601 stop_proxy(px);
Emeric Brunc47ba592020-10-07 10:13:10 +02003602 }
3603 px = px->next;
3604 }
3605
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003606 /* we might have to unbind some peers sections from some processes */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02003607 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003608 if (!curpeers->peers_fe)
3609 continue;
3610
3611 if (curpeers->peers_fe->bind_proc & (1UL << proc))
3612 continue;
3613
3614 stop_proxy(curpeers->peers_fe);
3615 /* disable this peer section so that it kills itself */
Willy Tarreau47c8c022015-09-28 16:39:25 +02003616 signal_unregister_handler(curpeers->sighandler);
Olivier Houchard3f795f72019-04-17 22:51:06 +02003617 task_destroy(curpeers->sync_task);
Willy Tarreau47c8c022015-09-28 16:39:25 +02003618 curpeers->sync_task = NULL;
Olivier Houchard3f795f72019-04-17 22:51:06 +02003619 task_destroy(curpeers->peers_fe->task);
Willy Tarreau47c8c022015-09-28 16:39:25 +02003620 curpeers->peers_fe->task = NULL;
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003621 curpeers->peers_fe = NULL;
3622 }
3623
William Lallemand2e8fad92018-11-13 16:18:23 +01003624 /*
3625 * This is only done in daemon mode because we might want the
3626 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3627 * we should now close the 3 first FDs to ensure that we can
3628 * detach from the TTY. We MUST NOT do it in other cases since
3629 * it would have already be done, and 0-2 would have been
3630 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003631 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003632 if ((global.mode & MODE_DAEMON) &&
3633 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003634 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003635 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003636 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003637 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3638 }
3639 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003640 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3641 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003642 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003643 }
3644
William Dauchye039f262019-11-17 15:47:15 +01003645 /* try our best to re-enable core dumps depending on system capabilities.
3646 * What is addressed here :
3647 * - remove file size limits
3648 * - remove core size limits
3649 * - mark the process dumpable again if it lost it due to user/group
3650 */
3651 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3652 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3653
3654#if defined(RLIMIT_FSIZE)
3655 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3656 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3657 ha_alert("[%s.main()] Failed to set the raise the maximum "
3658 "file size.\n", argv[0]);
Jerome Magnin4b1148f2021-01-12 20:19:38 +01003659 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003660 }
3661 else
3662 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003663 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003664 }
3665#endif
3666
3667#if defined(RLIMIT_CORE)
3668 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3669 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3670 ha_alert("[%s.main()] Failed to set the raise the core "
3671 "dump size.\n", argv[0]);
Jerome Magnin4b1148f2021-01-12 20:19:38 +01003672 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003673 }
3674 else
3675 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003676 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003677 }
3678#endif
3679
3680#if defined(USE_PRCTL)
3681 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3682 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3683 "no core will be dumped.\n", argv[0]);
3684#endif
3685 }
3686
Christopher Faulete3a5e352017-10-24 13:53:54 +02003687 global.mode &= ~MODE_STARTING;
Willy Tarreau4f60f162007-04-08 16:39:58 +02003688 /*
3689 * That's it : the central polling loop. Run until we stop.
3690 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02003691#ifdef USE_THREAD
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003692 {
William Lallemand1aab50b2018-06-07 09:46:01 +02003693 sigset_t blocked_sig, old_sig;
Willy Tarreauc40efc12019-05-03 09:22:44 +02003694 int i;
3695
William Lallemand1aab50b2018-06-07 09:46:01 +02003696 /* ensure the signals will be blocked in every thread */
3697 sigfillset(&blocked_sig);
3698 sigdelset(&blocked_sig, SIGPROF);
3699 sigdelset(&blocked_sig, SIGBUS);
3700 sigdelset(&blocked_sig, SIGFPE);
3701 sigdelset(&blocked_sig, SIGILL);
3702 sigdelset(&blocked_sig, SIGSEGV);
3703 pthread_sigmask(SIG_SETMASK, &blocked_sig, &old_sig);
3704
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003705 /* Create nbthread-1 thread. The first thread is the current process */
David Carliera92c5ce2019-09-13 05:03:12 +01003706 ha_thread_info[0].pthread = pthread_self();
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003707 for (i = 1; i < global.nbthread; i++)
David Carliera92c5ce2019-09-13 05:03:12 +01003708 pthread_create(&ha_thread_info[i].pthread, NULL, &run_thread_poll_loop, (void *)(long)i);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003709
Christopher Faulet62519022017-10-16 15:49:32 +02003710#ifdef USE_CPU_AFFINITY
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003711 /* Now the CPU affinity for all threads */
Amaury Denoyelled5955172021-04-15 16:29:58 +02003712
3713 /* If on multiprocess, use proc_t1 except for the first process.
3714 */
3715 if ((relative_pid - 1) > 0)
3716 global.cpu_map.thread[0] = global.cpu_map.proc_t1[relative_pid-1];
Willy Tarreau7764a572019-07-16 15:10:34 +02003717
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003718 for (i = 0; i < global.nbthread; i++) {
Christopher Fauletcb6a9452017-11-22 16:50:41 +01003719 if (global.cpu_map.proc[relative_pid-1])
Willy Tarreau81492c92019-05-03 09:41:23 +02003720 global.cpu_map.thread[i] &= global.cpu_map.proc[relative_pid-1];
Christopher Faulet62519022017-10-16 15:49:32 +02003721
Willy Tarreau421f02e2018-01-20 18:19:22 +01003722 if (i < MAX_THREADS && /* only the first 32/64 threads may be pinned */
Willy Tarreau81492c92019-05-03 09:41:23 +02003723 global.cpu_map.thread[i]) {/* only do this if the thread has a THREAD map */
David Carlier5e4c8e22019-09-13 05:12:58 +01003724#if defined(__APPLE__)
3725 int j;
3726 unsigned long cpu_map = global.cpu_map.thread[i];
3727
3728 while ((j = ffsl(cpu_map)) > 0) {
3729 thread_affinity_policy_data_t cpu_set = { j - 1 };
3730 thread_port_t mthread = pthread_mach_thread_np(ha_thread_info[i].pthread);
3731 thread_policy_set(mthread, THREAD_AFFINITY_POLICY, (thread_policy_t)&cpu_set, 1);
3732 cpu_map &= ~(1UL << (j - 1));
3733 }
3734#else
Olivier Houchard829aa242017-12-01 18:19:43 +01003735#if defined(__FreeBSD__) || defined(__NetBSD__)
3736 cpuset_t cpuset;
3737#else
3738 cpu_set_t cpuset;
3739#endif
3740 int j;
Willy Tarreau81492c92019-05-03 09:41:23 +02003741 unsigned long cpu_map = global.cpu_map.thread[i];
Olivier Houchard829aa242017-12-01 18:19:43 +01003742
3743 CPU_ZERO(&cpuset);
3744
3745 while ((j = ffsl(cpu_map)) > 0) {
3746 CPU_SET(j - 1, &cpuset);
Cyril Bontéd400ab32018-03-12 21:47:39 +01003747 cpu_map &= ~(1UL << (j - 1));
Olivier Houchard829aa242017-12-01 18:19:43 +01003748 }
David Carliera92c5ce2019-09-13 05:03:12 +01003749 pthread_setaffinity_np(ha_thread_info[i].pthread,
Olivier Houchard829aa242017-12-01 18:19:43 +01003750 sizeof(cpuset), &cpuset);
David Carlier5e4c8e22019-09-13 05:12:58 +01003751#endif
Olivier Houchard829aa242017-12-01 18:19:43 +01003752 }
Christopher Faulet1d17c102017-08-29 15:38:48 +02003753 }
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003754#endif /* !USE_CPU_AFFINITY */
3755
William Lallemand1aab50b2018-06-07 09:46:01 +02003756 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003757 haproxy_unblock_signals();
William Lallemand1aab50b2018-06-07 09:46:01 +02003758
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003759 /* Finally, start the poll loop for the first thread */
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02003760 run_thread_poll_loop(0);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003761
3762 /* Wait the end of other threads */
3763 for (i = 1; i < global.nbthread; i++)
David Carliera92c5ce2019-09-13 05:03:12 +01003764 pthread_join(ha_thread_info[i].pthread, NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003765
Christopher Fauletb79a94c2017-05-30 15:34:30 +02003766#if defined(DEBUG_THREAD) || defined(DEBUG_FULL)
3767 show_lock_stats();
3768#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003769 }
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003770#else /* ! USE_THREAD */
William Lallemandd3801c12018-09-11 10:06:23 +02003771 haproxy_unblock_signals();
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02003772 run_thread_poll_loop(0);
Christopher Faulet62519022017-10-16 15:49:32 +02003773#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003774
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003775 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776}
3777
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778/*
3779 * Local variables:
3780 * c-indent-level: 8
3781 * c-basic-offset: 8
3782 * End:
3783 */