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