]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: make SO_REUSEPORT configurable
authorLukas Tribus <luky-37@hotmail.com>
Mon, 12 Sep 2016 21:42:20 +0000 (21:42 +0000)
committerWilly Tarreau <w@1wt.eu>
Tue, 13 Sep 2016 05:56:03 +0000 (07:56 +0200)
With Linux officially introducing SO_REUSEPORT support in 3.9 and
its mainstream adoption we have seen more people running into strange
SO_REUSEPORT related issues (a process management issue turning into
hard to diagnose problems because the kernel load-balances between the
new and an obsolete haproxy instance).

Also some people simply want the guarantee that the bind fails when
the old process is still bound.

This change makes SO_REUSEPORT configurable, introducing the command
line argument "-dR" and the noreuseport configuration directive.

A backport to 1.6 should be considered.

doc/configuration.txt
include/types/global.h
src/cfgparse.c
src/haproxy.c
src/proto_tcp.c

index 1a7114e4bdd9b5cd8558cc2796d8f4322c05591c..52e6cf44bfeb59654a13f710f7397641adabb479 100644 (file)
@@ -578,6 +578,7 @@ The following keywords are supported in the "global" section :
    - nopoll
    - nosplice
    - nogetaddrinfo
+   - noreuseport
    - spread-checks
    - server-state-base
    - server-state-file
@@ -1130,6 +1131,10 @@ nogetaddrinfo
   Disables the use of getaddrinfo(3) for name resolving. It is equivalent to
   the command line argument "-dG". Deprecated gethostbyname(3) will be used.
 
+noreuseport
+  Disables the use of SO_REUSEPORT - see socket(7). It is equivalent to the
+  command line argument "-dR".
+
 spread-checks <0..50, in percent>
   Sometimes it is desirable to avoid sending agent and health checks to
   servers at exact intervals, for instance when many logical servers are
index 71eacf2960f2a27b6b8a44bf82013a1196821cf5..2a9bf5636b5e5662d1b9faa1e73f7f76badad214 100644 (file)
@@ -63,6 +63,7 @@
 /* platform-specific options */
 #define GTUNE_USE_SPLICE         (1<<4)
 #define GTUNE_USE_GAI            (1<<5)
+#define GTUNE_USE_REUSEPORT      (1<<6)
 
 /* Access level for a stats socket */
 #define ACCESS_LVL_NONE     0
index 09077d8ced2d0874a02dd5a7f7a6acb55bf3fb7b..7b58ef6bb70674deeb2c209bfa148b7c81a78cc9 100644 (file)
@@ -664,6 +664,11 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
                        goto out;
                global.tune.options &= ~GTUNE_USE_GAI;
        }
+       else if (!strcmp(args[0], "noreuseport")) {
+               if (alertif_too_many_args(0, file, linenum, args, &err_code))
+                       goto out;
+               global.tune.options &= ~GTUNE_USE_REUSEPORT;
+       }
        else if (!strcmp(args[0], "quiet")) {
                if (alertif_too_many_args(0, file, linenum, args, &err_code))
                        goto out;
index 96ecd0db6321ece65d2e1f61a200e2da2d825b90..b1c10b66d09e5c215d0d78caae0db4e1e95cf467 100644 (file)
@@ -458,6 +458,9 @@ void usage(char *name)
 #endif
 #if defined(USE_GETADDRINFO)
                "        -dG disables getaddrinfo() usage\n"
+#endif
+#if defined(SO_REUSEPORT)
+               "        -dR disables SO_REUSEPORT usage\n"
 #endif
                "        -dV disables SSL verify on servers side\n"
                "        -sf/-st [pid ]* finishes/terminates old pids.\n"
@@ -726,6 +729,9 @@ void init(int argc, char **argv)
 #if defined(USE_GETADDRINFO)
        global.tune.options |= GTUNE_USE_GAI;
 #endif
+#if defined(SO_REUSEPORT)
+       global.tune.options |= GTUNE_USE_REUSEPORT;
+#endif
 
        pid = getpid();
        progname = *argv;
@@ -768,6 +774,10 @@ void init(int argc, char **argv)
 #if defined(USE_GETADDRINFO)
                        else if (*flag == 'd' && flag[1] == 'G')
                                global.tune.options &= ~GTUNE_USE_GAI;
+#endif
+#if defined(SO_REUSEPORT)
+                       else if (*flag == 'd' && flag[1] == 'R')
+                               global.tune.options &= ~GTUNE_USE_REUSEPORT;
 #endif
                        else if (*flag == 'd' && flag[1] == 'V')
                                global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
index b614e6b5900098d938c56f8928412a0bd060a7ef..91d66881a5b01fed69a1af58b186d9651fa79ee6 100644 (file)
@@ -823,10 +823,10 @@ int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen)
                setsockopt(fd, SOL_SOCKET, SO_LINGER, &nolinger, sizeof(struct linger));
 
 #ifdef SO_REUSEPORT
-       /* OpenBSD supports this. As it's present in old libc versions of Linux,
-        * it might return an error that we will silently ignore.
+       /* OpenBSD and Linux 3.9 support this. As it's present in old libc versions of
+        * Linux, it might return an error that we will silently ignore.
         */
-       if (!ext)
+       if (!ext && (global.tune.options & GTUNE_USE_REUSEPORT))
                setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
 #endif