Hello community,

here is the log from the commit of package haproxy for openSUSE:Factory checked 
in at 2018-08-18 00:06:17
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/haproxy (Old)
 and      /work/SRC/openSUSE:Factory/.haproxy.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "haproxy"

Sat Aug 18 00:06:17 2018 rev:64 rq:629892 version:1.8.13~git4.c1bfcd00

Changes:
--------
--- /work/SRC/openSUSE:Factory/haproxy/haproxy.changes  2018-07-06 
10:48:20.434801390 +0200
+++ /work/SRC/openSUSE:Factory/.haproxy.new/haproxy.changes     2018-08-18 
00:06:26.891496554 +0200
@@ -1,0 +2,35 @@
+Thu Aug 16 07:08:12 UTC 2018 - kgronl...@suse.com
+
+- Update to version 1.8.13~git4.c1bfcd00:
+  * MINOR: dns: new DNS options to allow/prevent IP address duplication
+  * MINOR: dns: fix wrong score computation in dns_get_ip_from_response
+  * BUG/MEDIUM: queue: prevent a backup server from draining the proxy's 
connections
+  * BUG/MEDIUM: servers: check the queues once enabling a server
+  * MEDIUM: proxy_protocol: Convert IPs to v6 when protocols are mixed
+  * BUG/MEDIUM: threads: unbreak "bind" referencing an incorrect thread number
+  * MINOR: threads: move "nbthread" parsing to hathreads.c
+  * BUG/MEDIUM: threads: properly fix nbthreads == MAX_THREADS
+  * BUG/MINOR: threads: Handle nbthread == MAX_THREADS.
+  * BUG/MINOR: config: stick-table is not supported in defaults section
+  * BUG/MEDIUM: h2: prevent orphaned streams from blocking a connection forever
+  * BUG/MEDIUM: threads/sync: use sched_yield when available
+  * BUG/MINOR: servers: Don't make "server" in a frontend fatal.
+  * BUG/MEDIUM: stats: don't ask for more data as long as we're responding
+  * BUG/MEDIUM: stream-int: don't immediately enable reading when the buffer 
was reportedly full
+  * MINOR: h2: add the error code and the max/last stream IDs to "show fd"
+  * BUG/MEDIUM: threads: Fix the exit condition of the thread barrier
+  * MINOR: debug: Add checks for conn_stream flags
+  * MINOR: debug: Add check for CO_FL_WILL_UPDATE
+  * BUG/MINOR: http: Set brackets for the unlikely macro at the right place
+  * BUG/MEDIUM: h2: make sure the last stream closes the connection after a 
timeout
+  * BUG/MEDIUM: h2: never leave pending data in the output buffer on close
+  * BUG/MEDIUM: h2: don't accept new streams if conn_streams are still in 
excess
+  * MINOR: h2: add the mux and demux buffer lengths on "show fd"
+  * MINOR: h2: keep a count of the number of conn_streams attached to the mux
+  * BUG/MINOR: h2: remove accidental debug code introduced with show_fd 
function
+  * MINOR: h2: implement a basic "show_fd" function
+  * MINOR: mux: add a "show_fd" function to dump debugging information for 
"show fd"
+  * BUG/MINOR: ssl: properly ref-count the tls_keys entries
+  * MINOR: systemd: consider exit status 143 as successful
+
+-------------------------------------------------------------------

Old:
----
  haproxy-1.8.12~git0.8a200c71.tar.gz

New:
----
  haproxy-1.8.13~git4.c1bfcd00.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ haproxy.spec ++++++
--- /var/tmp/diff_new_pack.89jpTK/_old  2018-08-18 00:06:27.495498364 +0200
+++ /var/tmp/diff_new_pack.89jpTK/_new  2018-08-18 00:06:27.499498376 +0200
@@ -40,7 +40,7 @@
 %bcond_without  apparmor
 
 Name:           haproxy
-Version:        1.8.12~git0.8a200c71
+Version:        1.8.13~git4.c1bfcd00
 Release:        0
 #
 #

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.89jpTK/_old  2018-08-18 00:06:27.539498495 +0200
+++ /var/tmp/diff_new_pack.89jpTK/_new  2018-08-18 00:06:27.539498495 +0200
@@ -5,4 +5,4 @@
             <param 
name="url">http://git.haproxy.org/git/haproxy-1.7.git</param>
           <param 
name="changesrevision">640d526f8cdad00f7f5043b51f6a34f3f6ebb49f</param></service><service
 name="tar_scm">
                 <param 
name="url">http://git.haproxy.org/git/haproxy-1.8.git</param>
-              <param 
name="changesrevision">8a200c71bd0848752b71a1aed5727563962b3a1a</param></service></servicedata>
\ No newline at end of file
+              <param 
name="changesrevision">c1bfcd002f54d1d84a99282d13f875c2649f3d70</param></service></servicedata>
\ No newline at end of file

++++++ haproxy-1.8.12~git0.8a200c71.tar.gz -> 
haproxy-1.8.13~git4.c1bfcd00.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/CHANGELOG 
new/haproxy-1.8.13~git4.c1bfcd00/CHANGELOG
--- old/haproxy-1.8.12~git0.8a200c71/CHANGELOG  2018-06-27 16:27:32.000000000 
+0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/CHANGELOG  2018-08-09 05:59:42.000000000 
+0200
@@ -1,6 +1,36 @@
 ChangeLog :
 ===========
 
+2018/07/30 : 1.8.13
+    - MINOR: systemd: consider exit status 143 as successful
+    - BUG/MINOR: ssl: properly ref-count the tls_keys entries
+    - MINOR: mux: add a "show_fd" function to dump debugging information for 
"show fd"
+    - MINOR: h2: implement a basic "show_fd" function
+    - BUG/MINOR: h2: remove accidental debug code introduced with show_fd 
function
+    - MINOR: h2: keep a count of the number of conn_streams attached to the mux
+    - MINOR: h2: add the mux and demux buffer lengths on "show fd"
+    - BUG/MEDIUM: h2: don't accept new streams if conn_streams are still in 
excess
+    - BUG/MEDIUM: h2: never leave pending data in the output buffer on close
+    - BUG/MEDIUM: h2: make sure the last stream closes the connection after a 
timeout
+    - BUG/MINOR: http: Set brackets for the unlikely macro at the right place
+    - BUILD: Generate sha256 checksums in publish-release
+    - MINOR: debug: Add check for CO_FL_WILL_UPDATE
+    - MINOR: debug: Add checks for conn_stream flags
+    - BUG/MEDIUM: threads: Fix the exit condition of the thread barrier
+    - MINOR: h2: add the error code and the max/last stream IDs to "show fd"
+    - BUG/MEDIUM: stream-int: don't immediately enable reading when the buffer 
was reportedly full
+    - BUG/MEDIUM: stats: don't ask for more data as long as we're responding
+    - BUG/MINOR: servers: Don't make "server" in a frontend fatal.
+    - BUG/MEDIUM: threads/sync: use sched_yield when available
+    - BUG/MEDIUM: h2: prevent orphaned streams from blocking a connection 
forever
+    - BUG/MINOR: config: stick-table is not supported in defaults section
+    - BUG/MINOR: threads: Handle nbthread == MAX_THREADS.
+    - BUG/MEDIUM: threads: properly fix nbthreads == MAX_THREADS
+    - MINOR: threads: move "nbthread" parsing to hathreads.c
+    - BUG/MEDIUM: threads: unbreak "bind" referencing an incorrect thread 
number
+    - MEDIUM: proxy_protocol: Convert IPs to v6 when protocols are mixed
+    - SCRIPTS: git-show-backports: add missing quotes to "echo"
+
 2018/06/27 : 1.8.12
     - BUG/MAJOR: stick_table: Complete incomplete SEGV fix
     - MINOR: stick-tables: make stktable_release() do nothing on NULL
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/README 
new/haproxy-1.8.13~git4.c1bfcd00/README
--- old/haproxy-1.8.12~git0.8a200c71/README     2018-06-27 16:27:32.000000000 
+0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/README     2018-08-09 05:59:42.000000000 
+0200
@@ -3,7 +3,7 @@
                          ----------------------
                               version 1.8
                              willy tarreau
-                               2018/06/27
+                               2018/07/30
 
 
 1) How to build it
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/VERDATE 
new/haproxy-1.8.13~git4.c1bfcd00/VERDATE
--- old/haproxy-1.8.12~git0.8a200c71/VERDATE    2018-06-27 16:27:32.000000000 
+0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/VERDATE    2018-08-09 05:59:42.000000000 
+0200
@@ -1,2 +1,2 @@
 $Format:%ci$
-2018/06/27
+2018/07/30
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/VERSION 
new/haproxy-1.8.13~git4.c1bfcd00/VERSION
--- old/haproxy-1.8.12~git0.8a200c71/VERSION    2018-06-27 16:27:32.000000000 
+0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/VERSION    2018-08-09 05:59:42.000000000 
+0200
@@ -1 +1 @@
-1.8.12
+1.8.13
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/contrib/debug/flags.c 
new/haproxy-1.8.13~git4.c1bfcd00/contrib/debug/flags.c
--- old/haproxy-1.8.12~git0.8a200c71/contrib/debug/flags.c      2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/contrib/debug/flags.c      2018-08-09 
05:59:42.000000000 +0200
@@ -135,6 +135,7 @@
        SHOW_FLAG(f, CO_FL_ADDR_TO_SET);
        SHOW_FLAG(f, CO_FL_ADDR_FROM_SET);
        SHOW_FLAG(f, CO_FL_WAIT_ROOM);
+       SHOW_FLAG(f, CO_FL_WILL_UPDATE);
        SHOW_FLAG(f, CO_FL_XPRT_READY);
        SHOW_FLAG(f, CO_FL_CTRL_READY);
        SHOW_FLAG(f, CO_FL_CURR_WR_ENA);
@@ -149,6 +150,28 @@
        }
        putchar('\n');
 }
+void show_cs_flags(unsigned int f)
+{
+       printf("cs->flags = ");
+       if (!f) {
+               printf("0\n");
+               return;
+       }
+       SHOW_FLAG(f, CS_FL_EOS);
+       SHOW_FLAG(f, CS_FL_RCV_MORE);
+       SHOW_FLAG(f, CS_FL_ERROR);
+       SHOW_FLAG(f, CS_FL_SHWS);
+       SHOW_FLAG(f, CS_FL_SHWN);
+       SHOW_FLAG(f, CS_FL_SHRR);
+       SHOW_FLAG(f, CS_FL_SHRD);
+       SHOW_FLAG(f, CS_FL_DATA_WR_ENA);
+       SHOW_FLAG(f, CS_FL_DATA_RD_ENA);
+
+       if (f) {
+               printf("EXTRA(0x%08x)", f);
+       }
+       putchar('\n');
+}
 
 void show_si_et(unsigned int f)
 {
@@ -369,6 +392,7 @@
        show_strm_flags(flags);
        show_si_et(flags);
        show_si_flags(flags);
+       show_cs_flags(flags);
        show_conn_flags(flags);
        show_chn_flags(flags);
        show_chn_ana(flags);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haproxy-1.8.12~git0.8a200c71/contrib/systemd/haproxy.service.in 
new/haproxy-1.8.13~git4.c1bfcd00/contrib/systemd/haproxy.service.in
--- old/haproxy-1.8.12~git0.8a200c71/contrib/systemd/haproxy.service.in 
2018-06-27 16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/contrib/systemd/haproxy.service.in 
2018-08-09 05:59:42.000000000 +0200
@@ -10,6 +10,7 @@
 ExecReload=/bin/kill -USR2 $MAINPID
 KillMode=mixed
 Restart=always
+SuccessExitStatus=143
 Type=notify
 
 # The following lines leverage SystemD's sandboxing options to provide
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/doc/configuration.txt 
new/haproxy-1.8.13~git4.c1bfcd00/doc/configuration.txt
--- old/haproxy-1.8.12~git0.8a200c71/doc/configuration.txt      2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/doc/configuration.txt      2018-08-09 
05:59:42.000000000 +0200
@@ -4,7 +4,7 @@
                          ----------------------
                               version 1.8
                              willy tarreau
-                              2018/06/27
+                              2018/07/30
 
 
 This document covers the configuration language as implemented in the version
@@ -11623,6 +11623,40 @@
   after <count> consecutive successful health checks. This value defaults to 2
   if unspecified. See also the "check", "inter" and "fall" parameters.
 
+resolve-opts <option>,<option>,...
+  Comma separated list of options to apply to DNS resolution linked to this
+  server.
+
+  Available options:
+
+  * allow-dup-ip
+    By default, HAProxy prevents IP address duplication in a backend when DNS
+    resolution at runtime is in operation.
+    That said, for some cases, it makes sense that two servers (in the same
+    backend, being resolved by the same FQDN) have the same IP address.
+    For such case, simply enable this option.
+    This is the opposite of prevent-dup-ip.
+
+  * prevent-dup-ip
+    Ensure HAProxy's default behavior is enforced on a server: prevent re-using
+    an IP address already set to a server in the same backend and sharing the
+    same fqdn.
+    This is the opposite of allow-dup-ip.
+
+  Example:
+    backend b_myapp
+      default-server init-addr none resolvers dns
+      server s1 myapp.example.com:80 check resolve-opts allow-dup-ip
+      server s2 myapp.example.com:81 check resolve-opts allow-dup-ip
+
+  With the option allow-dup-ip set:
+  * if the nameserver returns a single IP address, then both servers will use
+    it
+  * If the nameserver returns 2 IP addresses, then each server will pick up a
+    different address
+
+  Default value: not set
+
 resolve-prefer <family>
   When DNS resolution is enabled for a server and multiple IP addresses from
   different families are returned, HAProxy will prefer using an IP address
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/examples/haproxy.spec 
new/haproxy-1.8.13~git4.c1bfcd00/examples/haproxy.spec
--- old/haproxy-1.8.12~git0.8a200c71/examples/haproxy.spec      2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/examples/haproxy.spec      2018-08-09 
05:59:42.000000000 +0200
@@ -1,6 +1,6 @@
 Summary: HA-Proxy is a TCP/HTTP reverse proxy for high availability 
environments
 Name: haproxy
-Version: 1.8.12
+Version: 1.8.13
 Release: 1
 License: GPL
 Group: System Environment/Daemons
@@ -74,6 +74,9 @@
 %attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name}
 
 %changelog
+* Mon Jul 30 2018 Willy Tarreau <w...@1wt.eu>
+- updated to 1.8.13
+
 * Wed Jun 27 2018 William Lallemand <wlallem...@haproxy.org>
 - updated to 1.8.12
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haproxy-1.8.12~git0.8a200c71/include/common/hathreads.h 
new/haproxy-1.8.13~git4.c1bfcd00/include/common/hathreads.h
--- old/haproxy-1.8.12~git0.8a200c71/include/common/hathreads.h 2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/include/common/hathreads.h 2018-08-09 
05:59:42.000000000 +0200
@@ -28,6 +28,12 @@
 extern THREAD_LOCAL unsigned int tid;     /* The thread id */
 extern THREAD_LOCAL unsigned long tid_bit; /* The bit corresponding to the 
thread id */
 
+/* Note about all_threads_mask :
+ *    - with threads support disabled, this symbol is defined as zero (0UL).
+ *    - with threads enabled, this variable is never zero, it contains the mask
+ *      of enabled threads. Thus if only one thread is enabled, it equals 1.
+ */
+
 #ifndef USE_THREAD
 
 #define MAX_THREADS 1
@@ -67,7 +73,7 @@
 
 #define HA_BARRIER() do { } while (0)
 
-#define THREAD_SYNC_INIT(m)  do { /* do nothing */ } while(0)
+#define THREAD_SYNC_INIT()   do { /* do nothing */ } while(0)
 #define THREAD_SYNC_ENABLE() do { /* do nothing */ } while(0)
 #define THREAD_WANT_SYNC()   do { /* do nothing */ } while(0)
 #define THREAD_ENTER_SYNC()  do { /* do nothing */ } while(0)
@@ -188,7 +194,7 @@
 
 #define HA_BARRIER() pl_barrier()
 
-#define THREAD_SYNC_INIT(m)   thread_sync_init(m)
+#define THREAD_SYNC_INIT()    thread_sync_init()
 #define THREAD_SYNC_ENABLE()  thread_sync_enable()
 #define THREAD_WANT_SYNC()    thread_want_sync()
 #define THREAD_ENTER_SYNC()   thread_enter_sync()
@@ -196,7 +202,7 @@
 #define THREAD_NO_SYNC()      thread_no_sync()
 #define THREAD_NEED_SYNC()    thread_need_sync()
 
-int  thread_sync_init(unsigned long mask);
+int  thread_sync_init();
 void thread_sync_enable(void);
 void thread_want_sync(void);
 void thread_enter_sync(void);
@@ -204,7 +210,7 @@
 int  thread_no_sync(void);
 int  thread_need_sync(void);
 
-extern unsigned long all_threads_mask;
+extern volatile unsigned long all_threads_mask;
 
 #define ha_sigmask(how, set, oldset)  pthread_sigmask(how, set, oldset)
 
@@ -692,5 +698,6 @@
 
 /* Dummy I/O handler used by the sync pipe.*/
 void thread_sync_io_handler(int fd);
+int parse_nbthread(const char *arg, char **err);
 
 #endif /* _COMMON_HATHREADS_H */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haproxy-1.8.12~git0.8a200c71/include/types/connection.h 
new/haproxy-1.8.13~git4.c1bfcd00/include/types/connection.h
--- old/haproxy-1.8.12~git0.8a200c71/include/types/connection.h 2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/include/types/connection.h 2018-08-09 
05:59:42.000000000 +0200
@@ -305,6 +305,7 @@
 
        struct conn_stream *(*attach)(struct connection *); /* Create and 
attach a conn_stream to an outgoing connection */
        void (*detach)(struct conn_stream *); /* Detach a conn_stream from an 
outgoing connection, when the request is done */
+       void (*show_fd)(struct chunk *, struct connection *); /* append some 
data about connection into chunk for "show fd" */
        unsigned int flags;                           /* some flags 
characterizing the mux's capabilities (MX_FL_*) */
        char name[8];                                 /* mux layer name, 
zero-terminated */
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/include/types/dns.h 
new/haproxy-1.8.13~git4.c1bfcd00/include/types/dns.h
--- old/haproxy-1.8.12~git0.8a200c71/include/types/dns.h        2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/include/types/dns.h        2018-08-09 
05:59:42.000000000 +0200
@@ -245,6 +245,8 @@
                } mask;
        } pref_net[SRV_MAX_PREF_NET];
        int pref_net_nb; /* The number of registered prefered networks. */
+       int accept_duplicate_ip; /* flag to indicate whether the associated 
object can use an IP address
+                                   already set to an other object of the same 
group */
 };
 
 /* Resolution structure associated to single server and used to manage name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haproxy-1.8.12~git0.8a200c71/include/types/ssl_sock.h 
new/haproxy-1.8.13~git4.c1bfcd00/include/types/ssl_sock.h
--- old/haproxy-1.8.12~git0.8a200c71/include/types/ssl_sock.h   2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/include/types/ssl_sock.h   2018-08-09 
05:59:42.000000000 +0200
@@ -54,6 +54,7 @@
        struct list list; /* Used to chain refs. */
        char *filename;
        int unique_id; /* Each pattern reference have unique id. */
+       int refcount;  /* number of users of this tls_keys_ref. */
        struct tls_sess_key *tlskeys;
        int tls_ticket_enc_index;
        __decl_hathreads(HA_RWLOCK_T lock); /* lock used to protect the ref */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/haproxy-1.8.12~git0.8a200c71/scripts/git-show-backports 
new/haproxy-1.8.13~git4.c1bfcd00/scripts/git-show-backports
--- old/haproxy-1.8.12~git0.8a200c71/scripts/git-show-backports 2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/scripts/git-show-backports 2018-08-09 
05:59:42.000000000 +0200
@@ -132,7 +132,7 @@
                done
                line="${line} |"
                if [ -z "$MISSING" -o $missing -gt 0 ]; then
-                       [ $((count++)) -gt 0 ] || echo $title
+                       [ $((count++)) -gt 0 ] || echo "$title"
                        [ "$QUIET" != "" -o $count -lt 20 ] || count=0
                        if [ -z "$UPSTREAM" -o "$upstream" = "none" -o -z 
"$upstream" ]; then
                                echo "$(short $ref) $line"
@@ -235,7 +235,7 @@
                        echo "---- Subject ----"
                else
                        # doing it this way prevents git from abusing the 
terminal
-                       echo $(git log -1 --pretty="%s" "$1")
+                       echo "$(git log -1 --pretty="%s" "$1")"
                        left_commits[${#left_commits[@]}]="$1"
                        comm=""
                        while [ -n "$1" -a "$1" != "-" -a "$1" != "|" ]; do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/scripts/publish-release 
new/haproxy-1.8.13~git4.c1bfcd00/scripts/publish-release
--- old/haproxy-1.8.12~git0.8a200c71/scripts/publish-release    2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/scripts/publish-release    2018-08-09 
05:59:42.000000000 +0200
@@ -159,14 +159,15 @@
 fi
 
 echo "Archiving sources for version $NEW ..."
-rm -f "${TARGET_DIR}/src${DEVEL}/haproxy-${NEW}.tar.gz"{,.md5}
+rm -f "${TARGET_DIR}/src${DEVEL}/haproxy-${NEW}.tar.gz"{,.md5,.sha256}
 if ! git archive --format=tar --prefix="haproxy-${NEW}/" "v$NEW" | \
      gzip -9 > "${TARGET_DIR}/src${DEVEL}/haproxy-${NEW}.tar.gz"; then
        die "Failed to produce the tar.gz archive"
 fi
 
 ( cd "$TARGET_DIR/src${DEVEL}" ; \
-  md5sum haproxy-$NEW.tar.gz > haproxy-$NEW.tar.gz.md5 )
+  md5sum haproxy-$NEW.tar.gz > haproxy-$NEW.tar.gz.md5 ; \
+  sha256sum haproxy-$NEW.tar.gz > haproxy-$NEW.tar.gz.sha256 )
 
 echo "Extracting doc ..."
 git show "v$NEW:CHANGELOG" > "$TARGET_DIR/src/CHANGELOG"
@@ -178,6 +179,6 @@
 
 echo "Done : ls -l ${TARGET_DIR}"
 ( cd "$TARGET_DIR" ;
-  ls -l src/CHANGELOG "src${DEVEL}/haproxy-${NEW}".tar.gz{,.md5} $(for i in 
"${DOC[@]}"; do echo "doc/${i#doc/}"{,.gz}; done)
+  ls -l src/CHANGELOG "src${DEVEL}/haproxy-${NEW}".tar.gz{,.md5,.sha256} $(for 
i in "${DOC[@]}"; do echo "doc/${i#doc/}"{,.gz}; done)
 )
 echo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/cfgparse.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/cfgparse.c
--- old/haproxy-1.8.12~git0.8a200c71/src/cfgparse.c     2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/cfgparse.c     2018-08-09 
05:59:42.000000000 +0200
@@ -1154,18 +1154,10 @@
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }
-               global.nbthread = atol(args[1]);
-#ifndef USE_THREAD
-               if (global.nbthread > 1) {
-                       ha_alert("HAProxy is not compiled with threads support, 
please check build options for USE_THREAD.\n");
-                       global.nbthread = 1;
-                       err_code |= ERR_ALERT | ERR_FATAL;
-                       goto out;
-               }
-#endif
-               if (global.nbthread < 1 || global.nbthread > MAX_THREADS) {
-                       ha_alert("parsing [%s:%d] : '%s' must be between 1 and 
%d (was %d).\n",
-                                file, linenum, args[0], MAX_THREADS, 
global.nbthread);
+               global.nbthread = parse_nbthread(args[1], &errmsg);
+               if (!global.nbthread) {
+                       ha_alert("parsing [%s:%d] : '%s' %s.\n",
+                                file, linenum, args[0], errmsg);
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }
@@ -4085,6 +4077,13 @@
                int myidx = 1;
                struct proxy *other;
 
+               if (curproxy == &defproxy) {
+                       ha_alert("parsing [%s:%d] : 'stick-table' is not 
supported in 'defaults' section.\n",
+                                file, linenum);
+                       err_code |= ERR_ALERT | ERR_FATAL;
+                       goto out;
+               }
+
                other = proxy_tbl_by_name(curproxy->id);
                if (other) {
                        ha_alert("parsing [%s:%d] : stick-table name '%s' 
conflicts with table declared in %s '%s' at %s:%d.\n",
@@ -7647,6 +7646,29 @@
                        } /* HTTP && bufsize < 16384 */
 #endif
 
+                       /* detect and address thread affinity inconsistencies */
+                       nbproc = 0;
+                       if (bind_conf->bind_proc)
+                               nbproc = my_ffsl(bind_conf->bind_proc);
+
+                       mask = bind_conf->bind_thread[nbproc - 1];
+                       if (mask && !(mask & (all_threads_mask ? 
all_threads_mask : 1UL))) {
+                               unsigned long new_mask = 0;
+
+                               while (mask) {
+                                       new_mask |= mask & (all_threads_mask ? 
all_threads_mask : 1UL);
+                                       mask >>= global.nbthread;
+                               }
+
+                               for (nbproc = 0; nbproc < LONGBITS; nbproc++) {
+                                       if (!bind_conf->bind_proc || 
(bind_conf->bind_proc & (1UL << nbproc)))
+                                               bind_conf->bind_thread[nbproc] 
= new_mask;
+                               }
+                               ha_warning("Proxy '%s': the thread range 
specified on the 'process' directive of 'bind %s' at [%s:%d] only refers to 
thread numbers out of the range defined by the global 'nbthread' directive. The 
thread numbers were remapped to existing threads instead (mask 0x%lx).\n",
+                                          curproxy->id, bind_conf->arg, 
bind_conf->file, bind_conf->line, new_mask);
+                       }
+
+                       /* detect process and nbproc affinity inconsistencies */
                        if (!bind_conf->bind_proc)
                                continue;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/cli.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/cli.c
--- old/haproxy-1.8.12~git0.8a200c71/src/cli.c  2018-06-27 16:27:32.000000000 
+0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/cli.c  2018-08-09 05:59:42.000000000 
+0200
@@ -841,8 +841,11 @@
                        else if (li)
                                chunk_appendf(&trash, " fe=%s", 
li->bind_conf->frontend->id);
 
-                       if (mux)
+                       if (mux) {
                                chunk_appendf(&trash, " mux=%s mux_ctx=%p", 
mux->name, ctx);
+                               if (mux->show_fd)
+                                       mux->show_fd(&trash, fdt.owner);
+                       }
                        else
                                chunk_appendf(&trash, " nomux");
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/connection.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/connection.c
--- old/haproxy-1.8.12~git0.8a200c71/src/connection.c   2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/connection.c   2018-08-09 
05:59:42.000000000 +0200
@@ -901,73 +901,71 @@
 int make_proxy_line_v1(char *buf, int buf_len, struct sockaddr_storage *src, 
struct sockaddr_storage *dst)
 {
        int ret = 0;
-
-       if (src && dst && src->ss_family == dst->ss_family && src->ss_family == 
AF_INET) {
-               ret = snprintf(buf + ret, buf_len - ret, "PROXY TCP4 ");
-               if (ret >= buf_len)
-                       return 0;
-
-               /* IPv4 src */
-               if (!inet_ntop(src->ss_family, &((struct sockaddr_in 
*)src)->sin_addr, buf + ret, buf_len - ret))
-                       return 0;
-
-               ret += strlen(buf + ret);
+       char * protocol;
+       char src_str[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
+       char dst_str[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
+       in_port_t src_port;
+       in_port_t dst_port;
+
+       if (   !src
+           || !dst
+           || (src->ss_family != AF_INET && src->ss_family != AF_INET6)
+           || (dst->ss_family != AF_INET && dst->ss_family != AF_INET6)) {
+               /* unknown family combination */
+               ret = snprintf(buf, buf_len, "PROXY UNKNOWN\r\n");
                if (ret >= buf_len)
                        return 0;
 
-               buf[ret++] = ' ';
-
-               /* IPv4 dst */
-               if (!inet_ntop(dst->ss_family, &((struct sockaddr_in 
*)dst)->sin_addr, buf + ret, buf_len - ret))
-                       return 0;
+               return ret;
+       }
 
-               ret += strlen(buf + ret);
-               if (ret >= buf_len)
+       /* IPv4 for both src and dst */
+       if (src->ss_family == AF_INET && dst->ss_family == AF_INET) {
+               protocol = "TCP4";
+               if (!inet_ntop(AF_INET, &((struct sockaddr_in *)src)->sin_addr, 
src_str, sizeof(src_str)))
                        return 0;
-
-               /* source and destination ports */
-               ret += snprintf(buf + ret, buf_len - ret, " %u %u\r\n",
-                               ntohs(((struct sockaddr_in *)src)->sin_port),
-                               ntohs(((struct sockaddr_in *)dst)->sin_port));
-               if (ret >= buf_len)
+               src_port = ((struct sockaddr_in *)src)->sin_port;
+               if (!inet_ntop(AF_INET, &((struct sockaddr_in *)dst)->sin_addr, 
dst_str, sizeof(dst_str)))
                        return 0;
+               dst_port = ((struct sockaddr_in *)dst)->sin_port;
        }
-       else if (src && dst && src->ss_family == dst->ss_family && 
src->ss_family == AF_INET6) {
-               ret = snprintf(buf + ret, buf_len - ret, "PROXY TCP6 ");
-               if (ret >= buf_len)
-                       return 0;
+       /* IPv6 for at least one of src and dst */
+       else {
+               struct in6_addr tmp;
 
-               /* IPv6 src */
-               if (!inet_ntop(src->ss_family, &((struct sockaddr_in6 
*)src)->sin6_addr, buf + ret, buf_len - ret))
-                       return 0;
+               protocol = "TCP6";
 
-               ret += strlen(buf + ret);
-               if (ret >= buf_len)
-                       return 0;
+               if (src->ss_family == AF_INET) {
+                       /* Convert src to IPv6 */
+                       v4tov6(&tmp, &((struct sockaddr_in *)src)->sin_addr);
+                       src_port = ((struct sockaddr_in *)src)->sin_port;
+               }
+               else {
+                       tmp = ((struct sockaddr_in6 *)src)->sin6_addr;
+                       src_port = ((struct sockaddr_in6 *)src)->sin6_port;
+               }
 
-               buf[ret++] = ' ';
-
-               /* IPv6 dst */
-               if (!inet_ntop(dst->ss_family, &((struct sockaddr_in6 
*)dst)->sin6_addr, buf + ret, buf_len - ret))
+               if (!inet_ntop(AF_INET6, &tmp, src_str, sizeof(src_str)))
                        return 0;
 
-               ret += strlen(buf + ret);
-               if (ret >= buf_len)
-                       return 0;
+               if (dst->ss_family == AF_INET) {
+                       /* Convert dst to IPv6 */
+                       v4tov6(&tmp, &((struct sockaddr_in *)dst)->sin_addr);
+                       dst_port = ((struct sockaddr_in *)dst)->sin_port;
+               }
+               else {
+                       tmp = ((struct sockaddr_in6 *)dst)->sin6_addr;
+                       dst_port = ((struct sockaddr_in6 *)dst)->sin6_port;
+               }
 
-               /* source and destination ports */
-               ret += snprintf(buf + ret, buf_len - ret, " %u %u\r\n",
-                               ntohs(((struct sockaddr_in6 *)src)->sin6_port),
-                               ntohs(((struct sockaddr_in6 *)dst)->sin6_port));
-               if (ret >= buf_len)
-                       return 0;
-       }
-       else {
-               /* unknown family combination */
-               ret = snprintf(buf, buf_len, "PROXY UNKNOWN\r\n");
-               if (ret >= buf_len)
+               if (!inet_ntop(AF_INET6, &tmp, dst_str, sizeof(dst_str)))
                        return 0;
        }
+
+       ret = snprintf(buf, buf_len, "PROXY %s %s %s %u %u\r\n", protocol, 
src_str, dst_str, ntohs(src_port), ntohs(dst_port));
+       if (ret >= buf_len)
+               return 0;
+
        return ret;
 }
 
@@ -1007,35 +1005,60 @@
                dst = &remote->addr.to;
        }
 
-       if (src && dst && src->ss_family == dst->ss_family && src->ss_family == 
AF_INET) {
-               if (buf_len < PP2_HDR_LEN_INET)
-                       return 0;
-               hdr->ver_cmd = PP2_VERSION | PP2_CMD_PROXY;
-               hdr->fam = PP2_FAM_INET | PP2_TRANS_STREAM;
-               hdr->addr.ip4.src_addr = ((struct sockaddr_in 
*)src)->sin_addr.s_addr;
-               hdr->addr.ip4.dst_addr = ((struct sockaddr_in 
*)dst)->sin_addr.s_addr;
-               hdr->addr.ip4.src_port = ((struct sockaddr_in *)src)->sin_port;
-               hdr->addr.ip4.dst_port = ((struct sockaddr_in *)dst)->sin_port;
-               ret = PP2_HDR_LEN_INET;
-       }
-       else if (src && dst && src->ss_family == dst->ss_family && 
src->ss_family == AF_INET6) {
-               if (buf_len < PP2_HDR_LEN_INET6)
-                       return 0;
-               hdr->ver_cmd = PP2_VERSION | PP2_CMD_PROXY;
-               hdr->fam = PP2_FAM_INET6 | PP2_TRANS_STREAM;
-               memcpy(hdr->addr.ip6.src_addr, &((struct sockaddr_in6 
*)src)->sin6_addr, 16);
-               memcpy(hdr->addr.ip6.dst_addr, &((struct sockaddr_in6 
*)dst)->sin6_addr, 16);
-               hdr->addr.ip6.src_port = ((struct sockaddr_in6 
*)src)->sin6_port;
-               hdr->addr.ip6.dst_port = ((struct sockaddr_in6 
*)dst)->sin6_port;
-               ret = PP2_HDR_LEN_INET6;
-       }
-       else {
+       /* At least one of src or dst is not of AF_INET or AF_INET6 */
+       if (  !src
+          || !dst
+          || (src->ss_family != AF_INET && src->ss_family != AF_INET6)
+          || (dst->ss_family != AF_INET && dst->ss_family != AF_INET6)) {
                if (buf_len < PP2_HDR_LEN_UNSPEC)
                        return 0;
                hdr->ver_cmd = PP2_VERSION | PP2_CMD_LOCAL;
                hdr->fam = PP2_FAM_UNSPEC | PP2_TRANS_UNSPEC;
                ret = PP2_HDR_LEN_UNSPEC;
        }
+       else {
+               /* IPv4 for both src and dst */
+               if (src->ss_family == AF_INET && dst->ss_family == AF_INET) {
+                       if (buf_len < PP2_HDR_LEN_INET)
+                               return 0;
+                       hdr->ver_cmd = PP2_VERSION | PP2_CMD_PROXY;
+                       hdr->fam = PP2_FAM_INET | PP2_TRANS_STREAM;
+                       hdr->addr.ip4.src_addr = ((struct sockaddr_in 
*)src)->sin_addr.s_addr;
+                       hdr->addr.ip4.src_port = ((struct sockaddr_in 
*)src)->sin_port;
+                       hdr->addr.ip4.dst_addr = ((struct sockaddr_in 
*)dst)->sin_addr.s_addr;
+                       hdr->addr.ip4.dst_port = ((struct sockaddr_in 
*)dst)->sin_port;
+                       ret = PP2_HDR_LEN_INET;
+               }
+               /* IPv6 for at least one of src and dst */
+               else {
+                       struct in6_addr tmp;
+
+                       if (buf_len < PP2_HDR_LEN_INET6)
+                               return 0;
+                       hdr->ver_cmd = PP2_VERSION | PP2_CMD_PROXY;
+                       hdr->fam = PP2_FAM_INET6 | PP2_TRANS_STREAM;
+                       if (src->ss_family == AF_INET) {
+                               v4tov6(&tmp, &((struct sockaddr_in 
*)src)->sin_addr);
+                               memcpy(hdr->addr.ip6.src_addr, &tmp, 16);
+                               hdr->addr.ip6.src_port = ((struct sockaddr_in 
*)src)->sin_port;
+                       }
+                       else {
+                               memcpy(hdr->addr.ip6.src_addr, &((struct 
sockaddr_in6 *)src)->sin6_addr, 16);
+                               hdr->addr.ip6.src_port = ((struct sockaddr_in6 
*)src)->sin6_port;
+                       }
+                       if (dst->ss_family == AF_INET) {
+                               v4tov6(&tmp, &((struct sockaddr_in 
*)dst)->sin_addr);
+                               memcpy(hdr->addr.ip6.dst_addr, &tmp, 16);
+                               hdr->addr.ip6.src_port = ((struct sockaddr_in 
*)src)->sin_port;
+                       }
+                       else {
+                               memcpy(hdr->addr.ip6.dst_addr, &((struct 
sockaddr_in6 *)dst)->sin6_addr, 16);
+                               hdr->addr.ip6.dst_port = ((struct sockaddr_in6 
*)dst)->sin6_port;
+                       }
+
+                       ret = PP2_HDR_LEN_INET6;
+               }
+       }
 
        if (conn_get_alpn(remote, &value, &value_len)) {
                if ((buf_len - ret) < sizeof(struct tlv))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/dns.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/dns.c
--- old/haproxy-1.8.12~git0.8a200c71/src/dns.c  2018-06-27 16:27:32.000000000 
+0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/dns.c  2018-08-09 05:59:42.000000000 
+0200
@@ -965,8 +965,10 @@
        int currentip_sel;
        int j;
        int score, max_score;
+       int allowed_duplicated_ip;
 
        family_priority   = dns_opts->family_prio;
+       allowed_duplicated_ip = dns_opts->accept_duplicate_ip;
        *newip = newip4   = newip6 = NULL;
        currentip_found   = 0;
        *newip_sin_family = AF_UNSPEC;
@@ -1027,10 +1029,15 @@
                }
 
                /* Check if the IP found in the record is already affected to a
-                * member of a group.  If yes, the score should be incremented
+                * member of a group.  If not, the score should be incremented
                 * by 2. */
-               if (owner && snr_check_ip_callback(owner, ip, &ip_type))
-                       continue;
+               if (owner && snr_check_ip_callback(owner, ip, &ip_type)) {
+                       if (!allowed_duplicated_ip) {
+                               continue;
+                       }
+               } else {
+                       score += 2;
+               }
 
                /* Check for current ip matching. */
                if (ip_type == currentip_sin_family &&
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/haproxy.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/haproxy.c
--- old/haproxy-1.8.12~git0.8a200c71/src/haproxy.c      2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/haproxy.c      2018-08-09 
05:59:42.000000000 +0200
@@ -3018,7 +3018,7 @@
                int          i;
                sigset_t     blocked_sig, old_sig;
 
-               THREAD_SYNC_INIT((1UL << global.nbthread) - 1);
+               THREAD_SYNC_INIT();
 
                /* Init tids array */
                for (i = 0; i < global.nbthread; i++)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/hathreads.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/hathreads.c
--- old/haproxy-1.8.12~git0.8a200c71/src/hathreads.c    2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/hathreads.c    2018-08-09 
05:59:42.000000000 +0200
@@ -11,6 +11,7 @@
  */
 
 #include <unistd.h>
+#include <stdlib.h>
 #include <fcntl.h>
 
 #include <common/cfgparse.h>
@@ -31,17 +32,17 @@
 static HA_SPINLOCK_T sync_lock;
 static int           threads_sync_pipe[2];
 static unsigned long threads_want_sync = 0;
-unsigned long all_threads_mask  = 0;
+volatile unsigned long all_threads_mask  = 1; // nbthread 1 assumed by default
 
 #if defined(DEBUG_THREAD) || defined(DEBUG_FULL)
 struct lock_stat lock_stats[LOCK_LABELS];
 #endif
 
-/* Initializes the sync point. It creates a pipe used by threads to wakup all
- * others when a sync is requested. It also initialize the mask of all create
+/* Initializes the sync point. It creates a pipe used by threads to wake up all
+ * others when a sync is requested. It also initializes the mask of all created
  * threads. It returns 0 on success and -1 if an error occurred.
  */
-int thread_sync_init(unsigned long mask)
+int thread_sync_init()
 {
        int rfd;
 
@@ -54,8 +55,6 @@
        fdtab[rfd].owner = thread_sync_io_handler;
        fdtab[rfd].iocb = thread_sync_io_handler;
        fd_insert(rfd, MAX_THREADS_MASK);
-
-       all_threads_mask = mask;
        return 0;
 }
 
@@ -109,8 +108,20 @@
 
        HA_ATOMIC_CAS(barrier, &old, 0);
        HA_ATOMIC_OR(barrier, tid_bit);
-       while (*barrier != all_threads_mask)
+
+       /* Note below: we need to wait for all threads to join here, but in
+        * case several threads are scheduled on the same CPU, busy polling
+        * will instead degrade the performance, forcing other threads to
+        * wait longer (typically in epoll_wait()). Let's use sched_yield()
+        * when available instead.
+        */
+       while ((*barrier & all_threads_mask) != all_threads_mask) {
+#if _POSIX_PRIORITY_SCHEDULING
+               sched_yield();
+#else
                pl_cpu_relax();
+#endif
+       }
 }
 
 /* Enter into the sync point and lock it if the current thread has requested a
@@ -162,4 +173,38 @@
        hap_register_build_opts("Built with multi-threading support.", 0);
 }
 
+#endif // USE_THREAD
+
+
+/* Parse the number of threads in argument <arg>, returns it and adjusts a few
+ * internal variables accordingly, or fails and returns zero with an error
+ * reason in <errmsg>. May be called multiple times while parsing.
+ */
+int parse_nbthread(const char *arg, char **err)
+{
+       long nbthread;
+       char *errptr;
+
+       nbthread = strtol(arg, &errptr, 10);
+       if (!*arg || *errptr) {
+               memprintf(err, "passed a missing or unparsable integer value in 
'%s'", arg);
+               return 0;
+       }
+
+#ifndef USE_THREAD
+       if (nbthread != 1) {
+               memprintf(err, "specified with a value other than 1 while 
HAProxy is not compiled with threads support. Please check build options for 
USE_THREAD");
+               return 0;
+       }
+#else
+       if (nbthread < 1 || nbthread > MAX_THREADS) {
+               memprintf(err, "value must be between 1 and %d (was %ld)", 
MAX_THREADS, nbthread);
+               return 0;
+       }
+
+       /* we proceed like this to be sure never to overflow the left shift */
+       all_threads_mask = 1UL << (nbthread - 1);
+       all_threads_mask |= all_threads_mask - 1;
 #endif
+       return nbthread;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/mux_h2.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/mux_h2.c
--- old/haproxy-1.8.12~git0.8a200c71/src/mux_h2.c       2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/mux_h2.c       2018-08-09 
05:59:42.000000000 +0200
@@ -54,11 +54,12 @@
 #define H2_CF_DEM_MROOM         0x00000020  // demux blocked on lack of room 
in mux buffer
 #define H2_CF_DEM_SALLOC        0x00000040  // demux blocked on lack of 
stream's request buffer
 #define H2_CF_DEM_SFULL         0x00000080  // demux blocked on stream request 
buffer full
-#define H2_CF_DEM_BLOCK_ANY     0x000000F0  // aggregate of the demux flags 
above except DALLOC/DFULL
+#define H2_CF_DEM_TOOMANY       0x00000100  // demux blocked waiting for some 
conn_streams to leave
+#define H2_CF_DEM_BLOCK_ANY     0x000001F0  // aggregate of the demux flags 
above except DALLOC/DFULL
 
 /* other flags */
-#define H2_CF_GOAWAY_SENT       0x00000100  // a GOAWAY frame was successfully 
sent
-#define H2_CF_GOAWAY_FAILED     0x00000200  // a GOAWAY frame failed to be sent
+#define H2_CF_GOAWAY_SENT       0x00001000  // a GOAWAY frame was successfully 
sent
+#define H2_CF_GOAWAY_FAILED     0x00002000  // a GOAWAY frame failed to be sent
 
 
 /* H2 connection state, in h2c->st0 */
@@ -113,7 +114,7 @@
        int timeout;        /* idle timeout duration in ticks */
        int shut_timeout;   /* idle timeout duration in ticks after GOAWAY was 
sent */
        unsigned int nb_streams;  /* number of streams in the tree */
-       /* 32 bit hole here */
+       unsigned int nb_cs;       /* number of attached conn_streams */
        struct task *task;  /* timeout management task */
        struct eb_root streams_by_id; /* all active streams by their ID */
        struct list send_list; /* list of blocked streams requesting to send */
@@ -252,6 +253,12 @@
        return 0;
 }
 
+/* returns true if the connection has too many conn_streams attached */
+static inline int h2_has_too_many_cs(const struct h2c *h2c)
+{
+       return h2c->nb_cs >= h2_settings_max_concurrent_streams;
+}
+
 /* re-enables receiving on mux <target> after a buffer was allocated. It 
returns
  * 1 if the allocation succeeds, in which case the connection is woken up, or 0
  * if it's impossible to wake up and we prefer to be woken up later.
@@ -402,6 +409,7 @@
        h2c->rcvd_c = 0;
        h2c->rcvd_s = 0;
        h2c->nb_streams = 0;
+       h2c->nb_cs = 0;
 
        h2c->dbuf = &buf_empty;
        h2c->dsi = -1;
@@ -685,14 +693,18 @@
 
        h2s->cs = cs;
        cs->ctx = h2s;
+       h2c->nb_cs++;
 
        if (stream_create_from_cs(cs) < 0)
                goto out_free_cs;
 
        /* OK done, the stream lives its own life now */
+       if (h2_has_too_many_cs(h2c))
+               h2c->flags |= H2_CF_DEM_TOOMANY;
        return h2s;
 
  out_free_cs:
+       h2c->nb_cs--;
        cs_free(cs);
  out_close:
        h2s_destroy(h2s);
@@ -1595,6 +1607,9 @@
        if (h2c->dbuf->i < h2c->dfl && h2c->dbuf->i < h2c->dbuf->size)
                return 0; // incomplete frame
 
+       if (h2c->flags & H2_CF_DEM_TOOMANY)
+               return 0; // too many cs still present
+
        /* now either the frame is complete or the buffer is complete */
        if (h2s->st != H2_SS_IDLE) {
                /* FIXME: stream already exists, this is only allowed for
@@ -2313,14 +2328,6 @@
                        h2_release(conn);
                        return -1;
                }
-               else {
-                       /* some streams still there, we need to signal them all 
and
-                        * wait for their departure.
-                        */
-                       __conn_xprt_stop_recv(conn);
-                       __conn_xprt_stop_send(conn);
-                       return 0;
-               }
        }
 
        if (!h2c->dbuf->i)
@@ -2336,6 +2343,7 @@
 
        /* adjust output polling */
        if (!(conn->flags & CO_FL_SOCK_WR_SH) &&
+           h2c->st0 != H2_CS_ERROR2 && !(h2c->flags & H2_CF_GOAWAY_FAILED) &&
            (h2c->st0 == H2_CS_ERROR ||
             h2c->mbuf->o ||
             (h2c->mws > 0 && !LIST_ISEMPTY(&h2c->fctl_list)) ||
@@ -2483,11 +2491,21 @@
 
        h2c = h2s->h2c;
        h2s->cs = NULL;
+       h2c->nb_cs--;
+       if (h2c->flags & H2_CF_DEM_TOOMANY &&
+           !h2_has_too_many_cs(h2c)) {
+               h2c->flags &= ~H2_CF_DEM_TOOMANY;
+               if (h2_recv_allowed(h2c)) {
+                       __conn_xprt_want_recv(h2c->conn);
+                       conn_xprt_want_send(h2c->conn);
+               }
+       }
 
        /* this stream may be blocked waiting for some data to leave (possibly
         * an ES or RST frame), so orphan it in this case.
         */
        if (!(cs->conn->flags & CO_FL_ERROR) &&
+           (h2c->st0 < H2_CS_ERROR) &&
            (h2s->flags & (H2_SF_BLK_MBUSY | H2_SF_BLK_MROOM | 
H2_SF_BLK_MFCTL)))
                return;
 
@@ -2511,6 +2529,7 @@
         */
        if (eb_is_empty(&h2c->streams_by_id) &&     /* don't close if streams 
exist */
            ((h2c->conn->flags & CO_FL_ERROR) ||    /* errors close immediately 
*/
+            (h2c->st0 >= H2_CS_ERROR && !h2c->task) || /* a timeout stroke 
earlier */
             (h2c->flags & H2_CF_GOAWAY_FAILED) ||
             (!h2c->mbuf->o &&  /* mux buffer empty, also process clean events 
below */
              (conn_xprt_read0_pending(h2c->conn) ||
@@ -3322,6 +3341,14 @@
        /* we may need to add END_STREAM */
        /* FIXME: we should also detect shutdown(w) below, but how ? Maybe we
         * could rely on the MSG_MORE flag as a hint for this ?
+        *
+        * FIXME: what we do here is not correct because we send end_stream
+        * before knowing if we'll have to send a HEADERS frame for the
+        * trailers. More importantly we're not consuming the trailing CRLF
+        * after the end of trailers, so it will be left to the caller to
+        * eat it. The right way to do it would be to measure trailers here
+        * and to send ES only if there are no trailers.
+        *
         */
        if (((h1m->flags & H1_MF_CLEN) && !(h1m->curr_len - size)) ||
            !h1m->curr_len || h1m->state >= HTTP_MSG_DONE)
@@ -3424,6 +3451,13 @@
                }
        }
 
+       if (h2s->st >= H2_SS_ERROR) {
+               /* trim any possibly pending data after we close (extra CR-LF,
+                * unprocessed trailers, abnormal extra data, ...)
+                */
+               bo_del(buf, buf->o);
+       }
+
        /* RST are sent similarly to frame acks */
        if (h2s->st == H2_SS_ERROR || h2s->flags & H2_SF_RST_RCVD) {
                cs->flags |= CS_FL_ERROR;
@@ -3446,6 +3480,41 @@
        return total;
 }
 
+/* for debugging with CLI's "show fd" command */
+static void h2_show_fd(struct chunk *msg, struct connection *conn)
+{
+       struct h2c *h2c = conn->mux_ctx;
+       struct h2s *h2s;
+       struct eb32_node *node;
+       int fctl_cnt = 0;
+       int send_cnt = 0;
+       int tree_cnt = 0;
+       int orph_cnt = 0;
+
+       if (!h2c)
+               return;
+
+       list_for_each_entry(h2s, &h2c->fctl_list, list)
+               fctl_cnt++;
+
+       list_for_each_entry(h2s, &h2c->send_list, list)
+               send_cnt++;
+
+       node = eb32_first(&h2c->streams_by_id);
+       while (node) {
+               h2s = container_of(node, struct h2s, by_id);
+               tree_cnt++;
+               if (!h2s->cs)
+                       orph_cnt++;
+               node = eb32_next(node);
+       }
+
+       chunk_appendf(msg, " st0=%d err=%d maxid=%d lastid=%d flg=0x%08x 
nbst=%u nbcs=%u"
+                     " fctl_cnt=%d send_cnt=%d tree_cnt=%d orph_cnt=%d 
dbuf=%u/%u mbuf=%u/%u",
+                     h2c->st0, h2c->errcode, h2c->max_id, h2c->last_sid, 
h2c->flags,
+                     h2c->nb_streams, h2c->nb_cs, fctl_cnt, send_cnt, 
tree_cnt, orph_cnt,
+                     h2c->dbuf->i, h2c->dbuf->size, h2c->mbuf->o, 
h2c->mbuf->size);
+}
 
 /*******************************************************/
 /* functions below are dedicated to the config parsers */
@@ -3517,6 +3586,7 @@
        .detach = h2_detach,
        .shutr = h2_shutr,
        .shutw = h2_shutw,
+       .show_fd = h2_show_fd,
        .flags = MX_FL_CLEAN_ABRT,
        .name = "H2",
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/proto_http.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/proto_http.c
--- old/haproxy-1.8.12~git0.8a200c71/src/proto_http.c   2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/proto_http.c   2018-08-09 
05:59:42.000000000 +0200
@@ -3451,7 +3451,7 @@
                    s->req.buf->p, &txn->hdr_idx, &ctx)) {
                        if (unlikely(http_header_add_tail2(&txn->req,
                            &txn->hdr_idx, "Early-Data: 1",
-                           strlen("Early-Data: 1"))) < 0) {
+                           strlen("Early-Data: 1")) < 0)) {
                                goto return_bad_req;
                         }
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/queue.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/queue.c
--- old/haproxy-1.8.12~git0.8a200c71/src/queue.c        2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/queue.c        2018-08-09 
05:59:42.000000000 +0200
@@ -117,7 +117,10 @@
        }
 
   ps_found:
-       if (srv_currently_usable(rsrv) && px->nbpend) {
+       if (srv_currently_usable(rsrv) && px->nbpend &&
+           (!(srv->flags & SRV_F_BACKUP) ||
+            (!px->srv_act &&
+             (srv == px->lbprm.fbck || (px->options & PR_O_USE_ALL_BK))))) {
                struct pendconn *pp;
 
                list_for_each_entry(pp, &px->pendconns, list) {
@@ -287,6 +290,15 @@
        if (!srv_currently_usable(s))
                return 0;
 
+       /* if this is a backup server and there are active servers or at
+        * least another backup server was elected, then this one must
+        * not dequeue requests from the proxy.
+        */
+       if ((s->flags & SRV_F_BACKUP) &&
+           (s->proxy->srv_act ||
+            ((s != s->proxy->lbprm.fbck) && !(s->proxy->options & 
PR_O_USE_ALL_BK))))
+               return 0;
+
        HA_SPIN_LOCK(PROXY_LOCK, &s->proxy->lock);
        maxconn = srv_dynamic_maxconn(s);
        list_for_each_entry_safe(p, pback, &s->proxy->pendconns, list) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/server.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/server.c
--- old/haproxy-1.8.12~git0.8a200c71/src/server.c       2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/server.c       2018-08-09 
05:59:42.000000000 +0200
@@ -1506,6 +1506,7 @@
        if (src->resolvers_id != NULL)
                srv->resolvers_id = strdup(src->resolvers_id);
        srv->dns_opts.family_prio = src->dns_opts.family_prio;
+       srv->dns_opts.accept_duplicate_ip = src->dns_opts.accept_duplicate_ip;
        if (srv->dns_opts.family_prio == AF_UNSPEC)
                srv->dns_opts.family_prio = AF_INET6;
        memcpy(srv->dns_opts.pref_net,
@@ -1897,7 +1898,7 @@
                        goto out;
                }
                else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, 
args[0], NULL))
-                       err_code |= ERR_ALERT | ERR_FATAL;
+                       err_code |= ERR_WARN;
 
                /* There is no mandatory first arguments for default server. */
                if (srv) {
@@ -2044,6 +2045,7 @@
                        newsrv = &curproxy->defsrv;
                        cur_arg = 1;
                        newsrv->dns_opts.family_prio = AF_INET6;
+                       newsrv->dns_opts.accept_duplicate_ip = 0;
                }
 
                while (*args[cur_arg]) {
@@ -2139,6 +2141,31 @@
                                newsrv->resolvers_id = strdup(args[cur_arg + 
1]);
                                cur_arg += 2;
                        }
+                       else if (!strcmp(args[cur_arg], "resolve-opts")) {
+                               char *p, *end;
+
+                               for (p = args[cur_arg + 1]; *p; p = end) {
+                                       /* cut on next comma */
+                                       for (end = p; *end && *end != ','; 
end++);
+                                       if (*end)
+                                               *(end++) = 0;
+
+                                       if (!strcmp(p, "allow-dup-ip")) {
+                                               
newsrv->dns_opts.accept_duplicate_ip = 1;
+                                       }
+                                       else if (!strcmp(p, "prevent-dup-ip")) {
+                                               
newsrv->dns_opts.accept_duplicate_ip = 0;
+                                       }
+                                       else {
+                                               ha_alert("parsing [%s:%d]: '%s' 
: unknown resolve-opts option '%s', supported methods are 'allow-dup-ip' and 
'prevent-dup-ip'.\n",
+                                                               file, linenum, 
args[cur_arg], p);
+                                               err_code |= ERR_ALERT | 
ERR_FATAL;
+                                               goto out;
+                                       }
+                               }
+
+                               cur_arg += 2;
+                       }
                        else if (!strcmp(args[cur_arg], "resolve-prefer")) {
                                if (!strcmp(args[cur_arg + 1], "ipv4"))
                                        newsrv->dns_opts.family_prio = AF_INET;
@@ -4774,6 +4801,19 @@
                if (prev_srv_count && s->proxy->srv_bck == 0 && 
s->proxy->srv_act == 0)
                        set_backend_down(s->proxy);
 
+               /* If the server is set with "on-marked-up 
shutdown-backup-sessions",
+                * and it's not a backup server and its effective weight is > 0,
+                * then it can accept new connections, so we shut down all 
streams
+                * on all backup servers.
+                */
+               if ((s->onmarkedup & HANA_ONMARKEDUP_SHUTDOWNBACKUPSESSIONS) &&
+                   !(s->flags & SRV_F_BACKUP) && s->next_eweight)
+                       srv_shutdown_backup_streams(s->proxy, SF_ERR_UP);
+
+               /* check if we can handle some connections queued at the proxy. 
We
+                * will take as many as we can handle.
+                */
+               xferred = pendconn_grab_from_px(s);
        }
        else if (s->next_admin & SRV_ADMF_MAINT) {
                /* remaining in maintenance mode, let's inform precisely about 
the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/ssl_sock.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/ssl_sock.c
--- old/haproxy-1.8.12~git0.8a200c71/src/ssl_sock.c     2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/ssl_sock.c     2018-08-09 
05:59:42.000000000 +0200
@@ -4814,7 +4814,7 @@
        ssl_sock_free_ssl_conf(&bind_conf->ssl_conf);
        free(bind_conf->ca_sign_file);
        free(bind_conf->ca_sign_pass);
-       if (bind_conf->keys_ref) {
+       if (bind_conf->keys_ref && !--bind_conf->keys_ref->refcount) {
                free(bind_conf->keys_ref->filename);
                free(bind_conf->keys_ref->tlskeys);
                LIST_DEL(&bind_conf->keys_ref->list);
@@ -7548,7 +7548,8 @@
        }
 
        keys_ref = tlskeys_ref_lookup(args[cur_arg + 1]);
-       if(keys_ref) {
+       if (keys_ref) {
+               keys_ref->refcount++;
                conf->keys_ref = keys_ref;
                return 0;
        }
@@ -7595,6 +7596,7 @@
        i -= 2;
        keys_ref->tls_ticket_enc_index = i < 0 ? 0 : i % TLS_TICKETS_NO;
        keys_ref->unique_id = -1;
+       keys_ref->refcount = 1;
        HA_RWLOCK_INIT(&keys_ref->lock);
        conf->keys_ref = keys_ref;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/stats.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/stats.c
--- old/haproxy-1.8.12~git0.8a200c71/src/stats.c        2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/stats.c        2018-08-09 
05:59:42.000000000 +0200
@@ -3130,7 +3130,15 @@
                }
        }
  out:
-       /* just to make gcc happy */ ;
+       /* we have left the request in the buffer for the case where we
+        * process a POST, and this automatically re-enables activity on
+        * read. It's better to indicate that we want to stop reading when
+        * we're sending, so that we know there's at most one direction
+        * deciding to wake the applet up. It saves it from looping when
+        * emitting large blocks into small TCP windows.
+        */
+       if (!channel_is_empty(res))
+               si_applet_stop_get(si);
 }
 
 /* Dump all fields from <info> into <out> using the "show info" format (name: 
value) */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/haproxy-1.8.12~git0.8a200c71/src/stream_interface.c 
new/haproxy-1.8.13~git4.c1bfcd00/src/stream_interface.c
--- old/haproxy-1.8.12~git0.8a200c71/src/stream_interface.c     2018-06-27 
16:27:32.000000000 +0200
+++ new/haproxy-1.8.13~git4.c1bfcd00/src/stream_interface.c     2018-08-09 
05:59:42.000000000 +0200
@@ -720,7 +720,7 @@
                                ic->rex = TICK_ETERNITY;
                        }
                }
-               else {
+               else if (!(si->flags & SI_FL_WAIT_ROOM) || !ic->buf->o) {
                        /* (re)start reading and update timeout. Note: we don't 
recompute the timeout
                         * everytime we get here, otherwise it would risk never 
to expire. We only
                         * update it if is was not yet set. The stream socket 
handler will already


Reply via email to