package: haproxy
[packages.git] / net / haproxy / patches / 0040-BUG-MAJOR-ev_select-disable-the-select-poller-if-max.patch
1 From f4096052b9397e29c3638651e7487c047081c00c Mon Sep 17 00:00:00 2001
2 From: Willy Tarreau <w@1wt.eu>
3 Date: Sun, 31 Mar 2013 14:41:15 +0200
4 Subject: [PATCH 40/42] BUG/MAJOR: ev_select: disable the select() poller if
5  maxsock > FD_SETSIZE
6
7 Some recent glibc updates have added controls on FD_SET/FD_CLR/FD_ISSET
8 that crash the program if it tries to use a file descriptor larger than
9 FD_SETSIZE.
10
11 For this reason, we now control the compatibility between global.maxsock
12 and FD_SETSIZE, and refuse to use select() if there too many FDs are
13 expected to be used. Note that on Solaris, FD_SETSIZE is already forced
14 to 65536, and that FreeBSD and OpenBSD allow it to be redefined, though
15 this is not needed thanks to kqueue which is much more efficient.
16
17 In practice, since poll() is enabled on all targets, it should not cause
18 any problem, unless it is explicitly disabled.
19
20 This change must be backported to 1.4 because the crashes caused by glibc
21 have already been reported on this version.
22 (cherry picked from commit 3fa87b1db95bc4d6640999462bdae620bff147c6)
23 ---
24  src/ev_select.c |  7 +++++++
25  src/haproxy.c   | 11 ++++++++++-
26  2 files changed, 17 insertions(+), 1 deletion(-)
27
28 diff --git a/src/ev_select.c b/src/ev_select.c
29 index 5a87282..1f35b54 100644
30 --- a/src/ev_select.c
31 +++ b/src/ev_select.c
32 @@ -170,6 +170,10 @@ REGPRM1 static int _do_init(struct poller *p)
33         int fd_set_bytes;
34  
35         p->private = NULL;
36 +
37 +       if (global.maxsock > FD_SETSIZE)
38 +               goto fail_revt;
39 +
40         fd_set_bytes = sizeof(fd_set) * (global.maxsock + FD_SETSIZE - 1) / FD_SETSIZE;
41  
42         if ((tmp_evts[DIR_RD] = (fd_set *)calloc(1, fd_set_bytes)) == NULL)
43 @@ -217,6 +221,9 @@ REGPRM1 static void _do_term(struct poller *p)
44   */
45  REGPRM1 static int _do_test(struct poller *p)
46  {
47 +       if (global.maxsock > FD_SETSIZE)
48 +               return 0;
49 +
50         return 1;
51  }
52  
53 diff --git a/src/haproxy.c b/src/haproxy.c
54 index c302143..1d588e1 100644
55 --- a/src/haproxy.c
56 +++ b/src/haproxy.c
57 @@ -711,7 +711,16 @@ void init(int argc, char **argv)
58                 list_pollers(stderr);
59  
60         if (!init_pollers()) {
61 -               Alert("No polling mechanism available.\n");
62 +               Alert("No polling mechanism available.\n"
63 +                     "  It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
64 +                     "  is too low on this platform to support maxconn and the number of listeners\n"
65 +                     "  and servers. You should rebuild haproxy specifying your system using TARGET=\n"
66 +                     "  in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
67 +                     "  global maxconn setting to accomodate the system's limitation. For reference,\n"
68 +                     "  FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
69 +                     "  %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
70 +                     "  check build settings using 'haproxy -vv'.\n\n",
71 +                     FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
72                 exit(1);
73         }
74         if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
75 -- 
76 1.8.1.5
77