/src/haproxy/src/limits.c
Line | Count | Source |
1 | | /* |
2 | | * Handlers for process resources limits. |
3 | | * |
4 | | * SPDX-License-Identifier: GPL-2.0-or-later. |
5 | | * |
6 | | */ |
7 | | |
8 | | #include <haproxy/global.h> |
9 | | #include <haproxy/limits.h> |
10 | | #include <haproxy/log.h> |
11 | | #include <haproxy/proxy.h> |
12 | | |
13 | | |
14 | | unsigned int rlim_fd_cur_at_boot = 0; |
15 | | unsigned int rlim_fd_max_at_boot = 0; |
16 | | |
17 | | /* Sets the RLIMIT_NOFILE setting to <new_limit> and returns the previous one |
18 | | * in <old_limit> if the pointer is not NULL, even if set_rlimit() fails. The |
19 | | * two pointers may point to the same variable as the copy happens after |
20 | | * setting the new value. The value is only changed if at least one of the new |
21 | | * limits is strictly higher than the current one, otherwise returns 0 without |
22 | | * changing anything. The getrlimit() or setrlimit() syscall return value is |
23 | | * returned and errno is preserved. |
24 | | */ |
25 | | int raise_rlim_nofile(struct rlimit *old_limit, struct rlimit *new_limit) |
26 | 0 | { |
27 | 0 | struct rlimit limit = { }; |
28 | 0 | int ret = 0; |
29 | |
|
30 | 0 | ret = getrlimit(RLIMIT_NOFILE, &limit); |
31 | |
|
32 | 0 | if (ret == 0 && |
33 | 0 | (limit.rlim_max < new_limit->rlim_max || |
34 | 0 | limit.rlim_cur < new_limit->rlim_cur)) { |
35 | 0 | ret = setrlimit(RLIMIT_NOFILE, new_limit); |
36 | 0 | } |
37 | |
|
38 | 0 | if (old_limit) |
39 | 0 | *old_limit = limit; |
40 | |
|
41 | 0 | return ret; |
42 | 0 | } |
43 | | |
44 | | /* Encapsulates the check of all supported for now process internal limits, |
45 | | * which could be provided via config or/and cmdline. Returns 1, if even only |
46 | | * one supported limit is set, otherwise 0. |
47 | | */ |
48 | | static int is_any_limit_configured() |
49 | 0 | { |
50 | 0 | int ret = 0; |
51 | |
|
52 | 0 | if (global.maxconn || global.rlimit_nofile || global.rlimit_memmax || |
53 | 0 | global.fd_hard_limit) |
54 | 0 | ret = 1; |
55 | |
|
56 | 0 | return ret; |
57 | 0 | } |
58 | | |
59 | | /* considers splicing proxies' maxconn, computes the ideal global.maxpipes |
60 | | * setting, and returns it. It may return -1 meaning "unlimited" if some |
61 | | * unlimited proxies have been found and the global.maxconn value is not yet |
62 | | * set. It may also return a value greater than maxconn if it's not yet set. |
63 | | * Note that a value of zero means there is no need for pipes. -1 is never |
64 | | * returned if global.maxconn is valid. |
65 | | */ |
66 | | int compute_ideal_maxpipes() |
67 | 0 | { |
68 | 0 | struct proxy *cur; |
69 | 0 | int nbfe = 0, nbbe = 0; |
70 | 0 | int unlimited = 0; |
71 | 0 | int pipes; |
72 | 0 | int max; |
73 | |
|
74 | 0 | for (cur = proxies_list; cur; cur = cur->next) { |
75 | 0 | if (cur->options2 & (PR_O2_SPLIC_ANY)) { |
76 | 0 | if (cur->cap & PR_CAP_FE) { |
77 | 0 | max = cur->maxconn; |
78 | 0 | nbfe += max; |
79 | 0 | if (!max) { |
80 | 0 | unlimited = 1; |
81 | 0 | break; |
82 | 0 | } |
83 | 0 | } |
84 | 0 | if (cur->cap & PR_CAP_BE) { |
85 | 0 | max = cur->fullconn ? cur->fullconn : global.maxconn; |
86 | 0 | nbbe += max; |
87 | 0 | if (!max) { |
88 | 0 | unlimited = 1; |
89 | 0 | break; |
90 | 0 | } |
91 | 0 | } |
92 | 0 | } |
93 | 0 | } |
94 | |
|
95 | 0 | pipes = MAX(nbfe, nbbe); |
96 | 0 | if (global.maxconn) { |
97 | 0 | if (pipes > global.maxconn || unlimited) |
98 | 0 | pipes = global.maxconn; |
99 | 0 | } else if (unlimited) { |
100 | 0 | pipes = -1; |
101 | 0 | } |
102 | |
|
103 | 0 | return pipes >= 4 ? pipes / 4 : pipes; |
104 | 0 | } |
105 | | |
106 | | /* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and |
107 | | * rlimits and computes an ideal maxconn. It's meant to be called only when |
108 | | * global.est_fd_usage contains the sum of listening FDs, before it is updated |
109 | | * based on maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN |
110 | | * (by default 100) is returned as it is expected that it will even run on tight |
111 | | * environments, and will maintain compatibility with previous packages that |
112 | | * used to rely on this value as the default one. The system will emit a |
113 | | * warning indicating how many FDs are missing anyway if needed. |
114 | | */ |
115 | | static int compute_ideal_maxconn() |
116 | 0 | { |
117 | 0 | int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend; |
118 | 0 | int engine_fds = global.ssl_used_async_engines * ssl_sides; |
119 | 0 | int pipes = compute_ideal_maxpipes(); |
120 | 0 | int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot); |
121 | 0 | int maxconn; |
122 | | |
123 | | /* we have to take into account these elements : |
124 | | * - number of engine_fds, which inflates the number of FD needed per |
125 | | * connection by this number. |
126 | | * - number of pipes per connection on average : for the unlimited |
127 | | * case, this is 0.5 pipe FDs per connection, otherwise it's a |
128 | | * fixed value of 2*pipes. |
129 | | * - two FDs per connection |
130 | | */ |
131 | | |
132 | | /* on some modern distros for archs like amd64 fs.nr_open (kernel max) |
133 | | * could be in order of 1 billion. Systemd since the version 256~rc3-3 |
134 | | * bumped fs.nr_open as the hard RLIMIT_NOFILE (rlim_fd_max_at_boot). |
135 | | * If we are started without any limits, we risk to finish with computed |
136 | | * maxconn = ~500000000, maxsock = ~2*maxconn. So, fdtab will be |
137 | | * extremely large and watchdog will kill the process, when it will try |
138 | | * to loop over the fdtab (see fd_reregister_all). Please note, that |
139 | | * fd_hard_limit is taken in account implicitly via 'ideal_maxconn' |
140 | | * value in all global.maxconn adjustments, when global.rlimit_memmax |
141 | | * is set: |
142 | | * |
143 | | * MIN(global.maxconn, capped by global.rlimit_memmax, ideal_maxconn); |
144 | | * |
145 | | * It also caps global.rlimit_nofile, if it couldn't be set as rlim_cur |
146 | | * and as rlim_max. So, fd_hard_limitit is a good parameter to serve as |
147 | | * a safeguard, when no haproxy-specific limits are set, i.e. |
148 | | * rlimit_memmax, maxconn, rlimit_nofile. But it must be kept as a zero, |
149 | | * if only one of these ha-specific limits is presented in config or in |
150 | | * the cmdline. |
151 | | */ |
152 | 0 | if (!is_any_limit_configured()) |
153 | 0 | global.fd_hard_limit = DEFAULT_MAXFD; |
154 | |
|
155 | 0 | if (global.fd_hard_limit && (remain > global.fd_hard_limit)) { |
156 | | /* cap remain only when global.fd_hard_limit > 0, i.e.: either |
157 | | * there were no any other limits set and it's defined by lines |
158 | | * above as DEFAULT_MAXFD (100), or fd_hard_limit is explicitly |
159 | | * provided in config. |
160 | | */ |
161 | 0 | remain = global.fd_hard_limit; |
162 | 0 | } |
163 | | |
164 | | /* subtract listeners and checks */ |
165 | 0 | remain -= global.est_fd_usage; |
166 | | |
167 | | /* Fixed pipes values : we only subtract them if they're not larger |
168 | | * than the remaining FDs because pipes are optional. |
169 | | */ |
170 | 0 | if (pipes >= 0 && pipes * 2 < remain) |
171 | 0 | remain -= pipes * 2; |
172 | |
|
173 | 0 | if (pipes < 0) { |
174 | | /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds. |
175 | | * = maxconn * (2 + 0.5 + engine_fds) |
176 | | * = maxconn * (4 + 1 + 2*engine_fds) / 2 |
177 | | */ |
178 | 0 | maxconn = 2 * remain / (5 + 2 * engine_fds); |
179 | 0 | } else { |
180 | | /* maxsock = maxconn * 2 + maxconn * engine_fds. |
181 | | * = maxconn * (2 + engine_fds) |
182 | | */ |
183 | 0 | maxconn = remain / (2 + engine_fds); |
184 | 0 | } |
185 | |
|
186 | 0 | return MAX(maxconn, DEFAULT_MAXCONN); |
187 | 0 | } |
188 | | |
189 | | /* computes the estimated maxsock value for the given maxconn based on the |
190 | | * possibly set global.maxpipes and existing partial global.maxsock. It may |
191 | | * temporarily change global.maxconn for the time needed to propagate the |
192 | | * computations, and will reset it. |
193 | | */ |
194 | | int compute_ideal_maxsock(int maxconn) |
195 | 0 | { |
196 | 0 | int maxpipes = global.maxpipes; |
197 | 0 | int maxsock = global.maxsock; |
198 | | |
199 | |
|
200 | 0 | if (!maxpipes) { |
201 | 0 | int old_maxconn = global.maxconn; |
202 | |
|
203 | 0 | global.maxconn = maxconn; |
204 | 0 | maxpipes = compute_ideal_maxpipes(); |
205 | 0 | global.maxconn = old_maxconn; |
206 | 0 | } |
207 | |
|
208 | 0 | maxsock += maxconn * 2; /* each connection needs two sockets */ |
209 | 0 | maxsock += maxpipes * 2; /* each pipe needs two FDs */ |
210 | 0 | maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */ |
211 | 0 | maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */ |
212 | | |
213 | | /* compute fd used by async engines */ |
214 | 0 | if (global.ssl_used_async_engines) { |
215 | 0 | int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend; |
216 | |
|
217 | 0 | maxsock += maxconn * sides * global.ssl_used_async_engines; |
218 | 0 | } |
219 | 0 | return maxsock; |
220 | 0 | } |
221 | | |
222 | | /* Tests if it is possible to set the current process's RLIMIT_NOFILE to |
223 | | * <maxsock>, then sets it back to the previous value. Returns non-zero if the |
224 | | * value is accepted, zero otherwise. This is used to determine if an |
225 | | * automatic limit may be applied or not. When it is not, the caller knows that |
226 | | * the highest we can do is the rlim_max at boot. In case of error, we return |
227 | | * that the setting is possible, so that we defer the error processing to the |
228 | | * final stage in charge of enforcing this. |
229 | | */ |
230 | | int check_if_maxsock_permitted(int maxsock) |
231 | 0 | { |
232 | 0 | struct rlimit orig_limit, test_limit; |
233 | 0 | int ret; |
234 | |
|
235 | 0 | if (global.fd_hard_limit && maxsock > global.fd_hard_limit) |
236 | 0 | return 0; |
237 | | |
238 | 0 | if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0) |
239 | 0 | return 1; |
240 | | |
241 | | /* don't go further if we can't even set to what we have */ |
242 | 0 | if (raise_rlim_nofile(NULL, &orig_limit) != 0) |
243 | 0 | return 1; |
244 | | |
245 | 0 | test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max); |
246 | 0 | test_limit.rlim_cur = test_limit.rlim_max; |
247 | 0 | ret = raise_rlim_nofile(NULL, &test_limit); |
248 | |
|
249 | 0 | if (raise_rlim_nofile(NULL, &orig_limit) != 0) |
250 | 0 | return 1; |
251 | | |
252 | 0 | return ret == 0; |
253 | 0 | } |
254 | | |
255 | | /* Calculates and sets global.maxconn and if compiled with USE_OPENSSL, |
256 | | * global.maxsslconn. |
257 | | */ |
258 | | void set_global_maxconn(void) |
259 | 0 | { |
260 | 0 | int ideal_maxconn = compute_ideal_maxconn(); |
261 | | |
262 | | /* It's a bit tricky. Maxconn defaults to the pre-computed value based |
263 | | * on rlim_fd_cur and the number of FDs in use due to the configuration, |
264 | | * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can |
265 | | * enforce a lower limit based on memmax. |
266 | | * |
267 | | * If memmax is set, then it depends on which values are set. If |
268 | | * maxsslconn is set, we use memmax to determine how many cleartext |
269 | | * connections may be added, and set maxconn to the sum of the two. |
270 | | * If maxconn is set and not maxsslconn, maxsslconn is computed from |
271 | | * the remaining amount of memory between memmax and the cleartext |
272 | | * connections. If neither are set, then it is considered that all |
273 | | * connections are SSL-capable, and maxconn is computed based on this, |
274 | | * then maxsslconn accordingly. We need to know if SSL is used on the |
275 | | * frontends, backends, or both, because when it's used on both sides, |
276 | | * we need twice the value for maxsslconn, but we only count the |
277 | | * handshake once since it is not performed on the two sides at the |
278 | | * same time (frontend-side is terminated before backend-side begins). |
279 | | * The SSL stack is supposed to have filled ssl_session_cost and |
280 | | * ssl_handshake_cost during its initialization. In any case, if |
281 | | * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for |
282 | | * maxconn in order to protect the system. |
283 | | */ |
284 | |
|
285 | 0 | if (!global.rlimit_memmax) { |
286 | 0 | if (global.maxconn == 0) { |
287 | 0 | global.maxconn = ideal_maxconn; |
288 | 0 | ha_notice("Automatically setting global.maxconn to %d.\n", global.maxconn); |
289 | 0 | } |
290 | 0 | } |
291 | | #ifdef USE_OPENSSL |
292 | | else if (!global.maxconn && !global.maxsslconn && |
293 | | (global.ssl_used_frontend || global.ssl_used_backend)) { |
294 | | /* memmax is set, compute everything automatically. Here we want |
295 | | * to ensure that all SSL connections will be served. We take |
296 | | * care of the number of sides where SSL is used, and consider |
297 | | * the worst case : SSL used on both sides and doing a handshake |
298 | | * simultaneously. Note that we can't have more than maxconn |
299 | | * handshakes at a time by definition, so for the worst case of |
300 | | * two SSL conns per connection, we count a single handshake. |
301 | | */ |
302 | | int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend; |
303 | | int64_t mem = global.rlimit_memmax * 1048576ULL; |
304 | | int retried = 0; |
305 | | |
306 | | mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry |
307 | | mem -= global.maxzlibmem; |
308 | | mem = mem * MEM_USABLE_RATIO; |
309 | | |
310 | | /* Principle: we test once to set maxconn according to the free |
311 | | * memory. If it results in values the system rejects, we try a |
312 | | * second time by respecting rlim_fd_max. If it fails again, we |
313 | | * go back to the initial value and will let the final code |
314 | | * dealing with rlimit report the error. That's up to 3 attempts. |
315 | | */ |
316 | | do { |
317 | | global.maxconn = mem / |
318 | | ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream |
319 | | sides * global.ssl_session_max_cost + // SSL buffers, one per side |
320 | | global.ssl_handshake_max_cost); // 1 handshake per connection max |
321 | | |
322 | | if (retried == 1) |
323 | | global.maxconn = MIN(global.maxconn, ideal_maxconn); |
324 | | global.maxconn = round_2dig(global.maxconn); |
325 | | #ifdef SYSTEM_MAXCONN |
326 | | if (global.maxconn > SYSTEM_MAXCONN) |
327 | | global.maxconn = SYSTEM_MAXCONN; |
328 | | #endif /* SYSTEM_MAXCONN */ |
329 | | global.maxsslconn = sides * global.maxconn; |
330 | | |
331 | | if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn))) |
332 | | break; |
333 | | } while (retried++ < 2); |
334 | | ha_notice("Automatically setting global.maxconn to %d and global.maxsslconn to %d.\n", |
335 | | global.maxconn, global.maxsslconn); |
336 | | } |
337 | | else if (!global.maxsslconn && |
338 | | (global.ssl_used_frontend || global.ssl_used_backend)) { |
339 | | /* memmax and maxconn are known, compute maxsslconn automatically. |
340 | | * maxsslconn being forced, we don't know how many of it will be |
341 | | * on each side if both sides are being used. The worst case is |
342 | | * when all connections use only one SSL instance because |
343 | | * handshakes may be on two sides at the same time. |
344 | | */ |
345 | | int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend; |
346 | | int64_t mem = global.rlimit_memmax * 1048576ULL; |
347 | | int64_t sslmem; |
348 | | |
349 | | mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry |
350 | | mem -= global.maxzlibmem; |
351 | | mem = mem * MEM_USABLE_RATIO; |
352 | | |
353 | | sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize); |
354 | | global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost); |
355 | | global.maxsslconn = round_2dig(global.maxsslconn); |
356 | | |
357 | | if (sslmem <= 0 || global.maxsslconn < sides) { |
358 | | ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too " |
359 | | "high for the global.memmax value (%d MB). The absolute maximum possible value " |
360 | | "without SSL is %d, but %d was found and SSL is in use.\n", |
361 | | global.rlimit_memmax, |
362 | | (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)), |
363 | | global.maxconn); |
364 | | exit(1); |
365 | | } |
366 | | |
367 | | if (global.maxsslconn > sides * global.maxconn) |
368 | | global.maxsslconn = sides * global.maxconn; |
369 | | |
370 | | if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) |
371 | | fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn); |
372 | | } |
373 | | #endif |
374 | 0 | else if (!global.maxconn) { |
375 | | /* memmax and maxsslconn are known/unused, compute maxconn automatically */ |
376 | 0 | int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend; |
377 | 0 | int64_t mem = global.rlimit_memmax * 1048576ULL; |
378 | 0 | int64_t clearmem; |
379 | 0 | int retried = 0; |
380 | |
|
381 | 0 | if (global.ssl_used_frontend || global.ssl_used_backend) |
382 | 0 | mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry |
383 | |
|
384 | 0 | mem -= global.maxzlibmem; |
385 | 0 | mem = mem * MEM_USABLE_RATIO; |
386 | |
|
387 | 0 | clearmem = mem; |
388 | 0 | if (sides) |
389 | 0 | clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn; |
390 | | |
391 | | /* Principle: we test once to set maxconn according to the free |
392 | | * memory. If it results in values the system rejects, we try a |
393 | | * second time by respecting rlim_fd_max. If it fails again, we |
394 | | * go back to the initial value and will let the final code |
395 | | * dealing with rlimit report the error. That's up to 3 attempts. |
396 | | */ |
397 | 0 | do { |
398 | 0 | global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize); |
399 | 0 | if (retried == 1) |
400 | 0 | global.maxconn = MIN(global.maxconn, ideal_maxconn); |
401 | 0 | global.maxconn = round_2dig(global.maxconn); |
402 | | #ifdef SYSTEM_MAXCONN |
403 | | if (global.maxconn > SYSTEM_MAXCONN) |
404 | | global.maxconn = SYSTEM_MAXCONN; |
405 | | #endif /* SYSTEM_MAXCONN */ |
406 | |
|
407 | 0 | if (clearmem <= 0 || !global.maxconn) { |
408 | 0 | ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too " |
409 | 0 | "high for the global.memmax value (%d MB). The absolute maximum possible value " |
410 | 0 | "is %d, but %d was found.\n", |
411 | 0 | global.rlimit_memmax, |
412 | 0 | (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)), |
413 | 0 | global.maxsslconn); |
414 | 0 | exit(1); |
415 | 0 | } |
416 | | |
417 | 0 | if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn))) |
418 | 0 | break; |
419 | 0 | } while (retried++ < 2); |
420 | | |
421 | 0 | if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) { |
422 | 0 | if (sides && global.maxsslconn > sides * global.maxconn) { |
423 | 0 | fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn " |
424 | 0 | "to be limited to %d. Better reduce global.maxsslconn to get more " |
425 | 0 | "room for extra connections.\n", global.maxsslconn, global.maxconn); |
426 | 0 | } |
427 | 0 | fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn); |
428 | 0 | } |
429 | 0 | } |
430 | 0 | } |
431 | | |
432 | | /* Sets the current and max nofile limits for the process. It may terminate the |
433 | | * process, if it can't raise FD limit and there is no 'no strict-limits' in the |
434 | | * global section. |
435 | | */ |
436 | | void apply_nofile_limit(void) |
437 | 0 | { |
438 | 0 | struct rlimit limit; |
439 | |
|
440 | 0 | if (!global.rlimit_nofile) |
441 | 0 | global.rlimit_nofile = global.maxsock; |
442 | |
|
443 | 0 | if (global.rlimit_nofile) { |
444 | 0 | limit.rlim_cur = global.rlimit_nofile; |
445 | 0 | limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur); |
446 | |
|
447 | 0 | if ((global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) || |
448 | 0 | raise_rlim_nofile(NULL, &limit) != 0) { |
449 | 0 | getrlimit(RLIMIT_NOFILE, &limit); |
450 | 0 | if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) |
451 | 0 | limit.rlim_cur = global.fd_hard_limit; |
452 | |
|
453 | 0 | if (global.tune.options & GTUNE_STRICT_LIMITS) { |
454 | | /* suggest roughly half of the limit minus used FDs for listeners, checks |
455 | | * etc. This will give roughly round numbers for 64k and above while |
456 | | * reserving enough listeners for small values such as 1024. |
457 | | */ |
458 | 0 | ha_alert("[%s.main()] Cannot raise FD limit to %d, current " |
459 | 0 | "limit is %d and hard limit is %d. You may prefer to let HAProxy " |
460 | 0 | "adjust the limit by itself; for this, please just drop any 'maxconn' and " |
461 | 0 | "'ulimit-n' from the global section, and possibly add 'fd-hard-limit' lower " |
462 | 0 | "than this hard limit. You may also force a new 'maxconn' value that is a bit " |
463 | 0 | "lower than half of the hard limit minus listeners and checks. This results in " |
464 | 0 | "roughly %u here.\n", |
465 | 0 | progname, global.rlimit_nofile, (int)limit.rlim_cur, (int)limit.rlim_max, |
466 | 0 | round_2dig((uint)MAX(limit.rlim_max - global.est_fd_usage, 3) * 49ULL / 100)); |
467 | 0 | exit(1); |
468 | 0 | } |
469 | 0 | else { |
470 | | /* try to set it to the max possible at least */ |
471 | 0 | limit.rlim_cur = limit.rlim_max; |
472 | 0 | if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) |
473 | 0 | limit.rlim_cur = global.fd_hard_limit; |
474 | |
|
475 | 0 | if (raise_rlim_nofile(&limit, &limit) == 0) |
476 | 0 | getrlimit(RLIMIT_NOFILE, &limit); |
477 | |
|
478 | 0 | ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n", |
479 | 0 | progname, global.rlimit_nofile, (int)limit.rlim_cur); |
480 | |
|
481 | 0 | ha_warning("[%s.main()] Cannot raise FD limit to %d, current " |
482 | 0 | "limit is %d and hard limit is %d. You may prefer to let HAProxy " |
483 | 0 | "adjust the limit by itself; for this, please just drop any 'maxconn' and " |
484 | 0 | "'ulimit-n' from the global section, and possibly add 'fd-hard-limit' lower " |
485 | 0 | "than this hard limit. You may also force a new 'maxconn' value that is a bit " |
486 | 0 | "lower than half of the hard limit minus listeners and checks. This results in " |
487 | 0 | "roughly %u here.\n", |
488 | 0 | progname, global.rlimit_nofile, (int)limit.rlim_cur, (int)limit.rlim_max, |
489 | 0 | round_2dig((uint)MAX(limit.rlim_max - global.est_fd_usage, 3) * 49ULL / 100)); |
490 | 0 | global.rlimit_nofile = limit.rlim_cur; |
491 | 0 | } |
492 | 0 | } |
493 | 0 | } |
494 | |
|
495 | 0 | } |
496 | | |
497 | | /* Sets the current and max memory limits for the process. It may terminate the |
498 | | * process, if it can't raise RLIMIT_DATA limit and there is no |
499 | | * 'no strict-limits' in the global section. |
500 | | */ |
501 | | void apply_memory_limit(void) |
502 | 0 | { |
503 | 0 | struct rlimit limit; |
504 | |
|
505 | 0 | if (global.rlimit_memmax) { |
506 | 0 | limit.rlim_cur = limit.rlim_max = |
507 | 0 | global.rlimit_memmax * 1048576ULL; |
508 | 0 | if (setrlimit(RLIMIT_DATA, &limit) == -1) { |
509 | 0 | if (global.tune.options & GTUNE_STRICT_LIMITS) { |
510 | 0 | ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n", |
511 | 0 | progname, global.rlimit_memmax); |
512 | 0 | exit(1); |
513 | 0 | } |
514 | 0 | else |
515 | 0 | ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n", |
516 | 0 | progname, global.rlimit_memmax); |
517 | 0 | } |
518 | 0 | } |
519 | |
|
520 | 0 | } |
521 | | |
522 | | /* Checks the current nofile limit via getrlimit and preallocates the |
523 | | * (limit.rlim_cur - 1) of FDs. It may terminate the process, if its current |
524 | | * nofile limit is lower than global.maxsock and there is no 'no strict-limits' |
525 | | * in the global section. |
526 | | */ |
527 | | void check_nofile_lim_and_prealloc_fd(void) |
528 | 0 | { |
529 | 0 | struct rlimit limit; |
530 | |
|
531 | 0 | limit.rlim_cur = limit.rlim_max = 0; |
532 | 0 | getrlimit(RLIMIT_NOFILE, &limit); |
533 | 0 | if (limit.rlim_cur < global.maxsock) { |
534 | 0 | if (global.tune.options & GTUNE_STRICT_LIMITS) { |
535 | 0 | ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. " |
536 | 0 | "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n", |
537 | 0 | progname, (int)limit.rlim_cur, global.maxconn, global.maxsock, |
538 | 0 | global.maxsock); |
539 | 0 | exit(1); |
540 | 0 | } |
541 | 0 | else |
542 | 0 | ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. " |
543 | 0 | "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n", |
544 | 0 | progname, (int)limit.rlim_cur, global.maxconn, global.maxsock, |
545 | 0 | global.maxsock); |
546 | 0 | } |
547 | | |
548 | 0 | if (global.prealloc_fd && fcntl((int)limit.rlim_cur - 1, F_GETFD) == -1) { |
549 | 0 | if (dup2(0, (int)limit.rlim_cur - 1) == -1) |
550 | 0 | ha_warning("[%s.main()] Unable to preallocate file descriptor %d : %s", |
551 | 0 | progname, (int)limit.rlim_cur - 1, strerror(errno)); |
552 | 0 | else |
553 | 0 | close((int)limit.rlim_cur - 1); |
554 | 0 | } |
555 | 0 | } |