Coverage Report

Created: 2026-01-10 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}