Hello community, here is the log from the commit of package haproxy for openSUSE:Factory checked in at 2018-05-08 13:38:45 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/haproxy (Old) and /work/SRC/openSUSE:Factory/.haproxy.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "haproxy" Tue May 8 13:38:45 2018 rev:60 rq:605117 version:1.8.8 Changes: -------- --- /work/SRC/openSUSE:Factory/haproxy/haproxy.changes 2018-03-28 10:30:01.491972780 +0200 +++ /work/SRC/openSUSE:Factory/.haproxy.new/haproxy.changes 2018-05-08 13:38:45.978464236 +0200 @@ -1,0 +2,44 @@ +Mon May 07 12:57:54 UTC 2018 - kgronl...@suse.com + +- Update to version 1.8.8: + * BUG/CRITICAL: h2: fix incorrect frame length check (VUL-0) (bsc#1089837) + * MINOR: cli: Ensure the CLI always outputs an error when it should + * BUG/MINOR: cli: Guard against NULL messages when using CLI_ST_PRINT_FREE + * BUG/MEDIUM: kqueue: When adding new events, provide an output to get errors. + * BUG/MINOR: http: Return an error in proxy mode when url2sa fails + * BUG/MEDIUM: connection: Make sure we have a mux before calling detach(). + * BUG/MEDIUM: threads: Fix the max/min calculation because of name clashes + +------------------------------------------------------------------- +Sat Apr 07 00:15:13 UTC 2018 - mrueck...@suse.de + +- Update to version 1.8.7: + * [RELEASE] Released version 1.8.7 + * MINOR: servers: Support alphanumeric characters for the server templates names + * BUG/MAJOR: cache: always initialize newly created objects + * [RELEASE] Released version 1.8.6 + * BUG/MINOR: spoe: Don't release the context buffer in .check_timeouts callbaclk + * BUG/MINOR: spoe: Initialize variables used during conf parsing before any check + * BUG/MAJOR: cache: fix random crashes caused by incorrect delete() on non-first blocks + * BUG/MINOR: fd: Don't clear the update_mask in fd_insert. + * BUG/MINOR: cache: fix "show cache" output + * BUG/MINOR: email-alert: Set the mailer port during alert initialization + * BUG/MINOR: checks: check the conn_stream's readiness and not the connection + * BUG/MEDIUM: h2: always add a stream to the send or fctl list when blocked + * BUILD/MINOR: threads: always export thread_sync_io_handler() + * BUG/MEDIUM: h2: don't consider pending data on detach if connection is in error + * BUG/MEDIUM: h2/threads: never release the task outside of the task handler + * MINOR: h2: fuse h2s_detach() and h2s_free() into h2s_destroy() + * MINOR: h2: always call h2s_detach() in h2_detach() + * BUG/MAJOR: h2: remove orphaned streams from the send list before closing + * MINOR: h2: provide and use h2s_detach() and h2s_free() + * CLEANUP: h2: rename misleading h2c_stream_close() to h2s_close() + * BUG/MINOR: hpack: fix harmless use of uninitialized value in hpack_dht_insert + * BUILD/MINOR: cli: fix a build warning introduced by last commit + * MINOR: cli: make "show fd" report the mux and mux_ctx pointers when available + * MINOR: cli/threads: make "show fd" report thread_sync_io_handler instead of "unknown" + * BUILD/MINOR: fix build when USE_THREAD is not defined + * BUG/MINOR: lua funtion hlua_socket_settimeout don't check negative values + * BUG/MINOR: lua: the function returns anything + +------------------------------------------------------------------- Old: ---- haproxy-1.8.5.tar.gz New: ---- haproxy-1.8.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ haproxy.spec ++++++ --- /var/tmp/diff_new_pack.PwITkv/_old 2018-05-08 13:38:46.746436516 +0200 +++ /var/tmp/diff_new_pack.PwITkv/_new 2018-05-08 13:38:46.750436372 +0200 @@ -40,7 +40,7 @@ %bcond_without apparmor Name: haproxy -Version: 1.8.5 +Version: 1.8.8 Release: 0 # # ++++++ _service ++++++ --- /var/tmp/diff_new_pack.PwITkv/_old 2018-05-08 13:38:46.790434928 +0200 +++ /var/tmp/diff_new_pack.PwITkv/_new 2018-05-08 13:38:46.790434928 +0200 @@ -3,8 +3,8 @@ <param name="url">http://git.haproxy.org/git/haproxy-1.8.git</param> <param name="scm">git</param> <param name="filename">haproxy</param> - <param name="versionformat">1.8.5</param> - <param name="revision">v1.8.5</param> + <param name="versionformat">1.8.8</param> + <param name="revision">v1.8.8</param> <param name="changesgenerate">enable</param> </service> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.PwITkv/_old 2018-05-08 13:38:46.814434062 +0200 +++ /var/tmp/diff_new_pack.PwITkv/_new 2018-05-08 13:38:46.818433918 +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">9a083d1428b655c0079b4355d764cc08d66757f2</param></service></servicedata> \ No newline at end of file + <param name="changesrevision">cd117685f0cff4f2f5577ef6a21eaae96ebd9f28</param></service></servicedata> \ No newline at end of file ++++++ haproxy-1.8.5.tar.gz -> haproxy-1.8.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/CHANGELOG new/haproxy-1.8.8/CHANGELOG --- old/haproxy-1.8.5/CHANGELOG 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/CHANGELOG 2018-04-19 17:20:31.000000000 +0200 @@ -1,6 +1,45 @@ ChangeLog : =========== +2018/04/19 : 1.8.8 + - BUG/MEDIUM: threads: Fix the max/min calculation because of name clashes + - BUG/MEDIUM: connection: Make sure we have a mux before calling detach(). + - BUG/MINOR: http: Return an error in proxy mode when url2sa fails + - BUG/MEDIUM: kqueue: When adding new events, provide an output to get errors. + - BUG/MINOR: cli: Guard against NULL messages when using CLI_ST_PRINT_FREE + - MINOR: cli: Ensure the CLI always outputs an error when it should + - DOC: lua: update the links to the config and Lua API + - BUG/CRITICAL: h2: fix incorrect frame length check + +2018/04/07 : 1.8.7 + - BUG/MAJOR: cache: always initialize newly created objects + - MINOR: servers: Support alphanumeric characters for the server templates names + +2018/04/05 : 1.8.6 + - BUG/MINOR: lua: the function returns anything + - BUG/MINOR: lua funtion hlua_socket_settimeout don't check negative values + - BUILD/MINOR: fix build when USE_THREAD is not defined + - MINOR: cli/threads: make "show fd" report thread_sync_io_handler instead of "unknown" + - MINOR: cli: make "show fd" report the mux and mux_ctx pointers when available + - BUILD/MINOR: cli: fix a build warning introduced by last commit + - BUG/MINOR: hpack: fix harmless use of uninitialized value in hpack_dht_insert + - CLEANUP: h2: rename misleading h2c_stream_close() to h2s_close() + - MINOR: h2: provide and use h2s_detach() and h2s_free() + - BUG/MAJOR: h2: remove orphaned streams from the send list before closing + - MINOR: h2: always call h2s_detach() in h2_detach() + - MINOR: h2: fuse h2s_detach() and h2s_free() into h2s_destroy() + - BUG/MEDIUM: h2/threads: never release the task outside of the task handler + - BUG/MEDIUM: h2: don't consider pending data on detach if connection is in error + - BUILD/MINOR: threads: always export thread_sync_io_handler() + - BUG/MEDIUM: h2: always add a stream to the send or fctl list when blocked + - BUG/MINOR: checks: check the conn_stream's readiness and not the connection + - BUG/MINOR: email-alert: Set the mailer port during alert initialization + - BUG/MINOR: cache: fix "show cache" output + - BUG/MINOR: fd: Don't clear the update_mask in fd_insert. + - BUG/MAJOR: cache: fix random crashes caused by incorrect delete() on non-first blocks + - BUG/MINOR: spoe: Initialize variables used during conf parsing before any check + - BUG/MINOR: spoe: Don't release the context buffer in .check_timeouts callbaclk + 2018/03/23 : 1.8.5 - BUG/MINOR: threads: fix missing thread lock labels for 1.8 - BUG/MEDIUM: ssl: Don't always treat SSL_ERROR_SYSCALL as unrecovarable. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/README new/haproxy-1.8.8/README --- old/haproxy-1.8.5/README 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/README 2018-04-19 17:20:31.000000000 +0200 @@ -3,7 +3,7 @@ ---------------------- version 1.8 willy tarreau - 2018/03/23 + 2018/04/19 1) How to build it diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/VERDATE new/haproxy-1.8.8/VERDATE --- old/haproxy-1.8.5/VERDATE 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/VERDATE 2018-04-19 17:20:31.000000000 +0200 @@ -1,2 +1,2 @@ $Format:%ci$ -2018/03/23 +2018/04/19 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/VERSION new/haproxy-1.8.8/VERSION --- old/haproxy-1.8.5/VERSION 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/VERSION 2018-04-19 17:20:31.000000000 +0200 @@ -1 +1 @@ -1.8.5 +1.8.8 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/doc/configuration.txt new/haproxy-1.8.8/doc/configuration.txt --- old/haproxy-1.8.5/doc/configuration.txt 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/doc/configuration.txt 2018-04-19 17:20:31.000000000 +0200 @@ -4,7 +4,7 @@ ---------------------- version 1.8 willy tarreau - 2018/03/23 + 2018/04/19 This document covers the configuration language as implemented in the version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/doc/lua.txt new/haproxy-1.8.8/doc/lua.txt --- old/haproxy-1.8.5/doc/lua.txt 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/doc/lua.txt 2018-04-19 17:20:31.000000000 +0200 @@ -1,6 +1,6 @@ Lua: Architecture and first steps ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - version 1.0 + version 1.8 author: Thierry FOURNIER contact: tfournier at arpalert dot org @@ -83,9 +83,9 @@ Reading the following documentation links is required to understand the current paragraph: - HAProxy doc: http://cbonte.github.io/haproxy-dconv/configuration-1.6.html + HAProxy doc: http://cbonte.github.io/haproxy-dconv/ Lua API: http://www.lua.org/manual/5.3/ - HAProxy API: http://www.arpalert.org/src/haproxy-lua-api/1.6/index.html + HAProxy API: http://www.arpalert.org/src/haproxy-lua-api/1.8/index.html Lua guide: http://www.lua.org/pil/ more about Lua choice diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/examples/haproxy.spec new/haproxy-1.8.8/examples/haproxy.spec --- old/haproxy-1.8.5/examples/haproxy.spec 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/examples/haproxy.spec 2018-04-19 17:20:31.000000000 +0200 @@ -1,6 +1,6 @@ Summary: HA-Proxy is a TCP/HTTP reverse proxy for high availability environments Name: haproxy -Version: 1.8.5 +Version: 1.8.8 Release: 1 License: GPL Group: System Environment/Daemons @@ -74,6 +74,15 @@ %attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name} %changelog +* Thu Apr 19 2018 Willy Tarreau <w...@1wt.eu> +- updated to 1.8.8 + +* Sat Apr 7 2018 Willy Tarreau <w...@1wt.eu> +- updated to 1.8.7 + +* Thu Apr 5 2018 Willy Tarreau <w...@1wt.eu> +- updated to 1.8.6 + * Fri Mar 23 2018 Willy Tarreau <w...@1wt.eu> - updated to 1.8.5 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/include/common/hathreads.h new/haproxy-1.8.8/include/common/hathreads.h --- old/haproxy-1.8.5/include/common/hathreads.h 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/include/common/hathreads.h 2018-04-19 17:20:31.000000000 +0200 @@ -41,26 +41,26 @@ #define HA_ATOMIC_OR(val, flags) ({*(val) |= (flags);}) #define HA_ATOMIC_XCHG(val, new) \ ({ \ - typeof(*(val)) __old = *(val); \ + typeof(*(val)) __old_xchg = *(val); \ *(val) = new; \ - __old; \ + __old_xchg; \ }) #define HA_ATOMIC_STORE(val, new) ({*(val) = new;}) #define HA_ATOMIC_UPDATE_MAX(val, new) \ ({ \ - typeof(*(val)) __new = (new); \ + typeof(*(val)) __new_max = (new); \ \ - if (*(val) < __new) \ - *(val) = __new; \ + if (*(val) < __new_max) \ + *(val) = __new_max; \ *(val); \ }) #define HA_ATOMIC_UPDATE_MIN(val, new) \ ({ \ - typeof(*(val)) __new = (new); \ + typeof(*(val)) __new_min = (new); \ \ - if (*(val) > __new) \ - *(val) = __new; \ + if (*(val) > __new_min) \ + *(val) = __new_min; \ *(val); \ }) @@ -120,38 +120,38 @@ * but only if it differs from the expected one. If it's the same it's a race * thus we try again to avoid confusing a possibly sensitive caller. */ -#define HA_ATOMIC_CAS(val, old, new) \ - ({ \ - typeof((val)) __val = (val); \ - typeof((old)) __oldp = (old); \ - typeof(*(old)) __oldv; \ - typeof((new)) __new = (new); \ - int __ret; \ - do { \ - __oldv = *__val; \ - __ret = __sync_bool_compare_and_swap(__val, *__oldp, __new); \ - } while (!__ret && *__oldp == __oldv); \ - if (!__ret) \ - *__oldp = __oldv; \ - __ret; \ +#define HA_ATOMIC_CAS(val, old, new) \ + ({ \ + typeof((val)) __val_cas = (val); \ + typeof((old)) __oldp_cas = (old); \ + typeof(*(old)) __oldv_cas; \ + typeof((new)) __new_cas = (new); \ + int __ret_cas; \ + do { \ + __oldv_cas = *__val_cas; \ + __ret_cas = __sync_bool_compare_and_swap(__val_cas, *__oldp_cas, __new_cas); \ + } while (!__ret_cas && *__oldp_cas == __oldv_cas); \ + if (!__ret_cas) \ + *__oldp_cas = __oldv_cas; \ + __ret_cas; \ }) -#define HA_ATOMIC_XCHG(val, new) \ - ({ \ - typeof((val)) __val = (val); \ - typeof(*(val)) __old; \ - typeof((new)) __new = (new); \ - do { __old = *__val; \ - } while (!__sync_bool_compare_and_swap(__val, __old, __new)); \ - __old; \ +#define HA_ATOMIC_XCHG(val, new) \ + ({ \ + typeof((val)) __val_xchg = (val); \ + typeof(*(val)) __old_xchg; \ + typeof((new)) __new_xchg = (new); \ + do { __old_xchg = *__val_xchg; \ + } while (!__sync_bool_compare_and_swap(__val_xchg, __old_xchg, __new_xchg)); \ + __old_xchg; \ }) -#define HA_ATOMIC_STORE(val, new) \ - ({ \ - typeof((val)) __val = (val); \ - typeof(*(val)) __old; \ - typeof((new)) __new = (new); \ - do { __old = *__val; \ - } while (!__sync_bool_compare_and_swap(__val, __old, __new)); \ +#define HA_ATOMIC_STORE(val, new) \ + ({ \ + typeof((val)) __val_store = (val); \ + typeof(*(val)) __old_store; \ + typeof((new)) __new_store = (new); \ + do { __old_store = *__val_store; \ + } while (!__sync_bool_compare_and_swap(__val_store, __old_store, __new_store)); \ }) #else /* gcc >= 4.7 */ @@ -166,19 +166,21 @@ #define HA_ATOMIC_UPDATE_MAX(val, new) \ ({ \ - typeof(*(val)) __old = *(val); \ - typeof(*(val)) __new = (new); \ + typeof(*(val)) __old_max = *(val); \ + typeof(*(val)) __new_max = (new); \ \ - while (__old < __new && !HA_ATOMIC_CAS(val, &__old, __new)); \ - (*val); \ + while (__old_max < __new_max && \ + !HA_ATOMIC_CAS(val, &__old_max, __new_max)); \ + *(val); \ }) #define HA_ATOMIC_UPDATE_MIN(val, new) \ ({ \ - typeof((*val)) __old = *(val); \ - typeof((*val)) __new = (new); \ + typeof(*(val)) __old_min = *(val); \ + typeof(*(val)) __new_min = (new); \ \ - while (__old > __new && !HA_ATOMIC_CAS(val, &__old, __new)); \ - (*val); \ + while (__old_min > __new_min && \ + !HA_ATOMIC_CAS(val, &__old_min, __new_min)); \ + *(val); \ }) #define HA_BARRIER() pl_barrier() @@ -678,4 +680,7 @@ #endif /* USE_THREAD */ +/* Dummy I/O handler used by the sync pipe.*/ +void thread_sync_io_handler(int fd); + #endif /* _COMMON_HATHREADS_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/include/proto/connection.h new/haproxy-1.8.8/include/proto/connection.h --- old/haproxy-1.8.5/include/proto/connection.h 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/include/proto/connection.h 2018-04-19 17:20:31.000000000 +0200 @@ -701,7 +701,20 @@ /* Release a conn_stream, and kill the connection if it was the last one */ static inline void cs_destroy(struct conn_stream *cs) { - cs->conn->mux->detach(cs); + if (cs->conn->mux) + cs->conn->mux->detach(cs); + else { + /* It's too early to have a mux, let's just destroy + * the connection + */ + struct connection *conn = cs->conn; + + conn_stop_tracking(conn); + conn_full_close(conn); + if (conn->destroy_cb) + conn->destroy_cb(conn); + conn_free(conn); + } cs_free(cs); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/include/proto/fd.h new/haproxy-1.8.8/include/proto/fd.h --- old/haproxy-1.8.5/include/proto/fd.h 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/include/proto/fd.h 2018-04-19 17:20:31.000000000 +0200 @@ -400,7 +400,6 @@ HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock); fdtab[fd].ev = 0; fdtab[fd].new = 1; - fdtab[fd].update_mask &= ~tid_bit; fdtab[fd].linger_risk = 0; fdtab[fd].cloned = 0; fdtab[fd].cache = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/cache.c new/haproxy-1.8.8/src/cache.c --- old/haproxy-1.8.5/src/cache.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/cache.c 2018-04-19 17:20:31.000000000 +0200 @@ -378,13 +378,11 @@ static void cache_free_blocks(struct shared_block *first, struct shared_block *block) { - if (first == block) { - struct cache_entry *object = (struct cache_entry *)first->data; - if (object->eb.key) { - eb32_delete(&object->eb); - object->eb.key = 0; - } - } + struct cache_entry *object = (struct cache_entry *)block->data; + + if (first == block && object->eb.key) + eb32_delete(&object->eb); + object->eb.key = 0; } /* @@ -448,6 +446,13 @@ } shctx_unlock(shctx); + /* the received memory is not initialized, we need at least to mark + * the object as not indexed yet. + */ + object = (struct cache_entry *)first->data; + object->eb.node.leaf_p = NULL; + object->eb.key = 0; + /* reserve space for the cache_entry structure */ first->len = sizeof(struct cache_entry); @@ -472,7 +477,6 @@ struct cache_entry *old; cache_ctx->first_block = first; - object = (struct cache_entry *)first->data; object->eb.key = (*(unsigned int *)&txn->cache_hash); memcpy(object->hash, txn->cache_hash, sizeof(object->hash)); @@ -499,8 +503,6 @@ out: /* if does not cache */ if (first) { - object = (struct cache_entry *)first->data; - shctx_lock(shctx); first->len = 0; object->eb.key = 0; @@ -963,9 +965,6 @@ struct cache* cache = appctx->ctx.cli.p0; struct stream_interface *si = appctx->owner; - chunk_reset(&trash); - - if (cache == NULL) { cache = LIST_ELEM((caches).n, typeof(struct cache *), list); } @@ -975,9 +974,14 @@ unsigned int next_key; struct cache_entry *entry; - chunk_appendf(&trash, "%p: %s (shctx:%p, available blocks:%d)\n", cache, cache->id, shctx_ptr(cache), shctx_ptr(cache)->nbav); - next_key = appctx->ctx.cli.i0; + if (!next_key) { + chunk_printf(&trash, "%p: %s (shctx:%p, available blocks:%d)\n", cache, cache->id, shctx_ptr(cache), shctx_ptr(cache)->nbav); + if (ci_putchk(si_ic(si), &trash) == -1) { + si_applet_cant_put(si); + return 0; + } + } appctx->ctx.cli.p0 = cache; @@ -987,11 +991,12 @@ node = eb32_lookup_ge(&cache->entries, next_key); if (!node) { shctx_unlock(shctx_ptr(cache)); + appctx->ctx.cli.i0 = 0; break; } entry = container_of(node, struct cache_entry, eb); - chunk_appendf(&trash, "%p hash:%u size:%u (%u blocks), refcount:%u, expire:%d\n", entry, (*(unsigned int *)entry->hash), block_ptr(entry)->len, block_ptr(entry)->block_count, block_ptr(entry)->refcount, entry->expire - (int)now.tv_sec); + chunk_printf(&trash, "%p hash:%u size:%u (%u blocks), refcount:%u, expire:%d\n", entry, (*(unsigned int *)entry->hash), block_ptr(entry)->len, block_ptr(entry)->block_count, block_ptr(entry)->refcount, entry->expire - (int)now.tv_sec); next_key = node->key + 1; appctx->ctx.cli.i0 = next_key; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/checks.c new/haproxy-1.8.8/src/checks.c --- old/haproxy-1.8.5/src/checks.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/checks.c 2018-04-19 17:20:31.000000000 +0200 @@ -1394,7 +1394,7 @@ __cs_stop_both(cs); task_wakeup(check->task, TASK_WOKEN_IO); } - else if (!(conn->flags & (CO_FL_XPRT_RD_ENA|CO_FL_XPRT_WR_ENA|CO_FL_HANDSHAKE))) { + else if (!(conn->flags & CO_FL_HANDSHAKE) && !(cs->flags & (CS_FL_DATA_RD_ENA|CS_FL_DATA_WR_ENA))) { /* we may get here if only a connection probe was required : we * don't have any data to send nor anything expected in response, * so the completion of the connection establishment is enough. @@ -3202,9 +3202,7 @@ check->xprt = mailer->xprt; check->addr = mailer->addr; - if (!get_host_port(&mailer->addr)) - /* Default to submission port */ - check->port = 587; + check->port = get_host_port(&mailer->addr); //check->server = s; if ((t = task_new(MAX_THREADS_MASK)) == NULL) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/cli.c new/haproxy-1.8.8/src/cli.c --- old/haproxy-1.8.5/src/cli.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/cli.c 2018-04-19 17:20:31.000000000 +0200 @@ -625,14 +625,20 @@ else si_applet_cant_put(si); break; - case CLI_ST_PRINT_FREE: - if (cli_output_msg(res, appctx->ctx.cli.err, LOG_ERR, cli_get_severity_output(appctx)) != -1) { + case CLI_ST_PRINT_FREE: { + const char *msg = appctx->ctx.cli.err; + + if (!msg) + msg = "Out of memory.\n"; + + if (cli_output_msg(res, msg, LOG_ERR, cli_get_severity_output(appctx)) != -1) { free(appctx->ctx.cli.err); appctx->st0 = CLI_ST_PROMPT; } else si_applet_cant_put(si); break; + } case CLI_ST_CALLBACK: /* use custom pointer */ if (appctx->io_handler) if (appctx->io_handler(appctx)) { @@ -777,6 +783,8 @@ struct listener *li = NULL; struct server *sv = NULL; struct proxy *px = NULL; + const struct mux_ops *mux = NULL; + void *ctx = NULL; uint32_t conn_flags = 0; fdt = fdtab[fd]; @@ -786,6 +794,8 @@ if (fdt.iocb == conn_fd_handler) { conn_flags = ((struct connection *)fdt.owner)->flags; + mux = ((struct connection *)fdt.owner)->mux; + ctx = ((struct connection *)fdt.owner)->mux_ctx; li = objt_listener(((struct connection *)fdt.owner)->target); sv = objt_server(((struct connection *)fdt.owner)->target); px = objt_proxy(((struct connection *)fdt.owner)->target); @@ -818,6 +828,7 @@ (fdt.iocb == conn_fd_handler) ? "conn_fd_handler" : (fdt.iocb == dgram_fd_handler) ? "dgram_fd_handler" : (fdt.iocb == listener_accept) ? "listener_accept" : + (fdt.iocb == thread_sync_io_handler) ? "thread_sync_io_handler" : "unknown", fdt.thread_mask, fdt.update_mask); @@ -829,6 +840,11 @@ chunk_appendf(&trash, " sv=%s/%s", sv->id, sv->proxy->id); else if (li) chunk_appendf(&trash, " fe=%s", li->bind_conf->frontend->id); + + if (mux) + chunk_appendf(&trash, " mux=%s mux_ctx=%p", mux->name, ctx); + else + chunk_appendf(&trash, " nomux"); } else if (fdt.iocb == listener_accept) { chunk_appendf(&trash, " l.st=%s fe=%s", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/ev_epoll.c new/haproxy-1.8.8/src/ev_epoll.c --- old/haproxy-1.8.5/src/ev_epoll.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/ev_epoll.c 2018-04-19 17:20:31.000000000 +0200 @@ -74,13 +74,15 @@ for (updt_idx = 0; updt_idx < fd_nbupdt; updt_idx++) { fd = fd_updt[updt_idx]; + HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock); + fdtab[fd].update_mask &= ~tid_bit; + if (!fdtab[fd].owner) { activity[tid].poll_drop++; + HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock); continue; } - HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock); - fdtab[fd].update_mask &= ~tid_bit; fdtab[fd].new = 0; eo = fdtab[fd].state; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/ev_kqueue.c new/haproxy-1.8.8/src/ev_kqueue.c --- old/haproxy-1.8.5/src/ev_kqueue.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/ev_kqueue.c 2018-04-19 17:20:31.000000000 +0200 @@ -31,6 +31,7 @@ /* private data */ static int kqueue_fd[MAX_THREADS]; // per-thread kqueue_fd static THREAD_LOCAL struct kevent *kev = NULL; +static struct kevent *kev_out = NULL; // Trash buffer for kevent() to write the eventlist in /* * kqueue() poller @@ -43,17 +44,21 @@ int updt_idx, en, eo; int changes = 0; + timeout.tv_sec = 0; + timeout.tv_nsec = 0; /* first, scan the update list to find changes */ for (updt_idx = 0; updt_idx < fd_nbupdt; updt_idx++) { fd = fd_updt[updt_idx]; + HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock); + fdtab[fd].update_mask &= ~tid_bit; + if (!fdtab[fd].owner) { activity[tid].poll_drop++; + HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock); continue; } - HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock); - fdtab[fd].update_mask &= ~tid_bit; fdtab[fd].new = 0; eo = fdtab[fd].state; @@ -87,13 +92,21 @@ HA_ATOMIC_OR(&fdtab[fd].polled_mask, tid_bit); } } - if (changes) - kevent(kqueue_fd[tid], kev, changes, NULL, 0, NULL); + if (changes) { +#ifdef EV_RECEIPT + kev[0].flags |= EV_RECEIPT; +#else + /* If EV_RECEIPT isn't defined, just add an invalid entry, + * so that we get an error and kevent() stops before scanning + * the kqueue. + */ + EV_SET(&kev[changes++], -1, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); +#endif + kevent(kqueue_fd[tid], kev, changes, kev_out, changes, &timeout); + } fd_nbupdt = 0; delta_ms = 0; - timeout.tv_sec = 0; - timeout.tv_nsec = 0; if (!exp) { delta_ms = MAX_DELAY_MS; @@ -156,8 +169,12 @@ { int fd; - /* we can have up to two events per fd (*/ - kev = calloc(1, sizeof(struct kevent) * 2 * global.maxsock); + /* we can have up to two events per fd, so allocate enough to store + * 2*fd event, and an extra one, in case EV_RECEIPT isn't defined, + * so that we can add an invalid entry and get an error, to avoid + * scanning the kqueue uselessly. + */ + kev = calloc(1, sizeof(struct kevent) * (2 * global.maxsock + 1)); if (kev == NULL) goto fail_alloc; @@ -200,6 +217,15 @@ { p->private = NULL; + /* we can have up to two events per fd, so allocate enough to store + * 2*fd event, and an extra one, in case EV_RECEIPT isn't defined, + * so that we can add an invalid entry and get an error, to avoid + * scanning the kqueue uselessly. + */ + kev_out = calloc(1, sizeof(struct kevent) * (2 * global.maxsock + 1)); + if (!kev_out) + goto fail_alloc; + kqueue_fd[tid] = kqueue(); if (kqueue_fd[tid] < 0) goto fail_fd; @@ -209,6 +235,9 @@ return 1; fail_fd: + free(kev_out); + kev_out = NULL; +fail_alloc: p->pref = 0; return 0; } @@ -226,6 +255,10 @@ p->private = NULL; p->pref = 0; + if (kev_out) { + free(kev_out); + kev_out = NULL; + } } /* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/ev_poll.c new/haproxy-1.8.8/src/ev_poll.c --- old/haproxy-1.8.5/src/ev_poll.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/ev_poll.c 2018-04-19 17:20:31.000000000 +0200 @@ -73,13 +73,15 @@ for (updt_idx = 0; updt_idx < fd_nbupdt; updt_idx++) { fd = fd_updt[updt_idx]; + HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock); + fdtab[fd].update_mask &= ~tid_bit; + if (!fdtab[fd].owner) { activity[tid].poll_drop++; + HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock); continue; } - HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock); - fdtab[fd].update_mask &= ~tid_bit; fdtab[fd].new = 0; eo = fdtab[fd].state; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/ev_select.c new/haproxy-1.8.8/src/ev_select.c --- old/haproxy-1.8.5/src/ev_select.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/ev_select.c 2018-04-19 17:20:31.000000000 +0200 @@ -55,13 +55,15 @@ for (updt_idx = 0; updt_idx < fd_nbupdt; updt_idx++) { fd = fd_updt[updt_idx]; + HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock); + fdtab[fd].update_mask &= ~tid_bit; + if (!fdtab[fd].owner) { activity[tid].poll_drop++; + HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock); continue; } - HA_SPIN_LOCK(FD_LOCK, &fdtab[fd].lock); - fdtab[fd].update_mask &= ~tid_bit; fdtab[fd].new = 0; eo = fdtab[fd].state; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/flt_spoe.c new/haproxy-1.8.8/src/flt_spoe.c --- old/haproxy-1.8.5/src/flt_spoe.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/flt_spoe.c 2018-04-19 17:20:31.000000000 +0200 @@ -2988,10 +2988,8 @@ { struct spoe_context *ctx = filter->ctx; - if (tick_is_expired(ctx->process_exp, now_ms)) { + if (tick_is_expired(ctx->process_exp, now_ms)) s->pending_events |= TASK_WOKEN_MSG; - spoe_release_buffer(&ctx->buffer, &ctx->buffer_wait); - } } /* Called when we are ready to filter data on a channel */ @@ -3767,6 +3765,11 @@ char *file = NULL, *engine = NULL; int ret, pos = *cur_arg + 1; + LIST_INIT(&curmsgs); + LIST_INIT(&curgrps); + LIST_INIT(&curmphs); + LIST_INIT(&curgphs); + conf = calloc(1, sizeof(*conf)); if (conf == NULL) { memprintf(err, "%s: out of memory", args[*cur_arg]); @@ -3815,10 +3818,6 @@ curproxy = px; curagent = NULL; curmsg = NULL; - LIST_INIT(&curmsgs); - LIST_INIT(&curgrps); - LIST_INIT(&curmphs); - LIST_INIT(&curgphs); ret = readcfgfile(file); curproxy = NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/hathreads.c new/haproxy-1.8.8/src/hathreads.c --- old/haproxy-1.8.5/src/hathreads.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/hathreads.c 2018-04-19 17:20:31.000000000 +0200 @@ -21,6 +21,11 @@ THREAD_LOCAL unsigned int tid = 0; THREAD_LOCAL unsigned long tid_bit = (1UL << 0); +/* Dummy I/O handler used by the sync pipe.*/ +void thread_sync_io_handler(int fd) +{ +} + #ifdef USE_THREAD static HA_SPINLOCK_T sync_lock; @@ -32,9 +37,6 @@ struct lock_stat lock_stats[LOCK_LABELS]; #endif -/* Dummy I/O handler used by the sync pipe.*/ -static void thread_sync_io_handler(int fd) { } - /* 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 * threads. It returns 0 on success and -1 if an error occurred. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/hlua.c new/haproxy-1.8.8/src/hlua.c --- old/haproxy-1.8.5/src/hlua.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/hlua.c 2018-04-19 17:20:31.000000000 +0200 @@ -2467,6 +2467,10 @@ socket = MAY_LJMP(hlua_checksocket(L, 1)); tmout = MAY_LJMP(luaL_checkinteger(L, 2)) * 1000; + /* Check for negative values */ + if (tmout < 0) + WILL_LJMP(luaL_error(L, "settimeout: cannot set negatives values")); + /* Check if we run on the same thread than the xreator thread. * We cannot access to the socket if the thread is different. */ @@ -2490,6 +2494,7 @@ s->res.wto = tmout; xref_unlock(&socket->xref, peer); + lua_pushinteger(L, 1); return 1; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/hpack-tbl.c new/haproxy-1.8.8/src/hpack-tbl.c --- old/haproxy-1.8.5/src/hpack-tbl.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/hpack-tbl.c 2018-04-19 17:20:31.000000000 +0200 @@ -261,15 +261,11 @@ if (!hpack_dht_make_room(dht, name.len + value.len)) return 0; - used = dht->used; - prev = head = dht->head; - wrap = dht->wrap; - tail = hpack_dht_get_tail(dht); - /* Now there is enough room in the table, that's guaranteed by the * protocol, but not necessarily where we need it. */ + used = dht->used; if (!used) { /* easy, the table was empty */ dht->front = dht->head = 0; @@ -281,6 +277,10 @@ } /* compute the new head, used and wrap position */ + prev = head = dht->head; + wrap = dht->wrap; + tail = hpack_dht_get_tail(dht); + used++; head++; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/map.c new/haproxy-1.8.8/src/map.c --- old/haproxy-1.8.5/src/map.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/map.c 2018-04-19 17:20:31.000000000 +0200 @@ -726,15 +726,21 @@ return 1; } - /* Try to delete the entry. */ + /* Try to modify the entry. */ err = NULL; HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); if (!pat_ref_set_by_id(appctx->ctx.map.ref, ref, args[4], &err)) { HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); - if (err) + if (err) { memprintf(&err, "%s.\n", err); - appctx->ctx.cli.err = err; - appctx->st0 = CLI_ST_PRINT_FREE; + appctx->ctx.cli.err = err; + appctx->st0 = CLI_ST_PRINT_FREE; + } + else { + appctx->ctx.cli.severity = LOG_ERR; + appctx->ctx.cli.msg = "Failed to update an entry.\n"; + appctx->st0 = CLI_ST_PRINT; + } return 1; } HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); @@ -747,10 +753,16 @@ HA_SPIN_LOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); if (!pat_ref_set(appctx->ctx.map.ref, args[3], args[4], &err)) { HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); - if (err) + if (err) { memprintf(&err, "%s.\n", err); - appctx->ctx.cli.err = err; - appctx->st0 = CLI_ST_PRINT_FREE; + appctx->ctx.cli.err = err; + appctx->st0 = CLI_ST_PRINT_FREE; + } + else { + appctx->ctx.cli.severity = LOG_ERR; + appctx->ctx.cli.msg = "Failed to update an entry.\n"; + appctx->st0 = CLI_ST_PRINT; + } return 1; } HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); @@ -832,10 +844,16 @@ ret = pat_ref_add(appctx->ctx.map.ref, args[3], NULL, &err); HA_SPIN_UNLOCK(PATREF_LOCK, &appctx->ctx.map.ref->lock); if (!ret) { - if (err) + if (err) { memprintf(&err, "%s.\n", err); - appctx->ctx.cli.err = err; - appctx->st0 = CLI_ST_PRINT_FREE; + appctx->ctx.cli.err = err; + appctx->st0 = CLI_ST_PRINT_FREE; + } + else { + appctx->ctx.cli.severity = LOG_ERR; + appctx->ctx.cli.msg = "Failed to add an entry.\n"; + appctx->st0 = CLI_ST_PRINT; + } return 1; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/mux_h2.c new/haproxy-1.8.8/src/mux_h2.c --- old/haproxy-1.8.5/src/mux_h2.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/mux_h2.c 2018-04-19 17:20:31.000000000 +0200 @@ -484,8 +484,8 @@ HA_SPIN_UNLOCK(BUF_WQ_LOCK, &buffer_wq_lock); if (h2c->task) { - task_delete(h2c->task); - task_free(h2c->task); + h2c->task->context = NULL; + task_wakeup(h2c->task, TASK_WOKEN_OTHER); h2c->task = NULL; } @@ -630,18 +630,27 @@ return ret; } -/* marks stream <h2s> as CLOSED for connection <h2c> and decrement the number - * of active streams for this connection if the stream was not yet closed. - * Please use this exclusively before closing a stream to ensure stream count - * is well maintained. +/* marks stream <h2s> as CLOSED and decrement the number of active streams for + * its connection if the stream was not yet closed. Please use this exclusively + * before closing a stream to ensure stream count is well maintained. */ -static inline void h2c_stream_close(struct h2c *h2c, struct h2s *h2s) +static inline void h2s_close(struct h2s *h2s) { if (h2s->st != H2_SS_CLOSED) h2s->h2c->nb_streams--; h2s->st = H2_SS_CLOSED; } +/* detaches an H2 stream from its H2C and releases it to the H2S pool. */ +static void h2s_destroy(struct h2s *h2s) +{ + h2s_close(h2s); + LIST_DEL(&h2s->list); + LIST_INIT(&h2s->list); + eb32_delete(&h2s->by_id); + pool_free(pool_head_h2s, h2s); +} + /* creates a new stream <id> on the h2c connection and returns it, or NULL in * case of memory allocation error. */ @@ -686,9 +695,7 @@ out_free_cs: cs_free(cs); out_close: - h2c->nb_streams--; - eb32_delete(&h2s->by_id); - pool_free(pool_head_h2s, h2s); + h2s_destroy(h2s); h2s = NULL; out: return h2s; @@ -924,7 +931,7 @@ ignore: h2s->flags |= H2_SF_RST_SENT; - h2c_stream_close(h2c, h2s); + h2s_close(h2s); return ret; } @@ -988,7 +995,7 @@ ignore: if (h2s->st > H2_SS_IDLE && h2s->st < H2_SS_CLOSED) { h2s->flags |= H2_SF_RST_SENT; - h2c_stream_close(h2c, h2s); + h2s_close(h2s); } return ret; @@ -1066,9 +1073,7 @@ if (!h2s->cs) { /* this stream was already orphaned */ - h2c_stream_close(h2c, h2s); - eb32_delete(&h2s->by_id); - pool_free(pool_head_h2s, h2s); + h2s_destroy(h2s); continue; } @@ -1084,7 +1089,7 @@ else if (flags & CS_FL_EOS && h2s->st == H2_SS_OPEN) h2s->st = H2_SS_HREM; else if (flags & CS_FL_EOS && h2s->st == H2_SS_HLOC) - h2c_stream_close(h2c, h2s); + h2s_close(h2s); } } @@ -1551,7 +1556,7 @@ return 1; h2s->errcode = h2_get_n32(h2c->dbuf, 0); - h2c_stream_close(h2c, h2s); + h2s_close(h2s); if (h2s->cs) { h2s->cs->flags |= CS_FL_EOS | CS_FL_ERROR; @@ -1781,7 +1786,7 @@ goto fail; } - if ((int)hdr.len < 0 || (int)hdr.len > h2c->mfs) { + if ((int)hdr.len < 0 || (int)hdr.len > global.tune.bufsize) { /* RFC7540#3.5: a GOAWAY frame MAY be omitted */ h2c_error(h2c, H2_ERR_FRAME_SIZE_ERROR); h2c->st0 = H2_CS_ERROR2; @@ -1811,7 +1816,7 @@ if (!h2_peek_frame_hdr(h2c->dbuf, &hdr)) break; - if ((int)hdr.len < 0 || (int)hdr.len > h2c->mfs) { + if ((int)hdr.len < 0 || (int)hdr.len > global.tune.bufsize) { h2c_error(h2c, H2_ERR_FRAME_SIZE_ERROR); h2c->st0 = H2_CS_ERROR; break; @@ -2099,9 +2104,7 @@ h2s->cs->flags &= ~CS_FL_DATA_WR_ENA; else { /* just sent the last frame for this orphaned stream */ - h2c_stream_close(h2c, h2s); - eb32_delete(&h2s->by_id); - pool_free(pool_head_h2s, h2s); + h2s_destroy(h2s); } } } @@ -2142,9 +2145,7 @@ h2s->cs->flags &= ~CS_FL_DATA_WR_ENA; else { /* just sent the last frame for this orphaned stream */ - h2c_stream_close(h2c, h2s); - eb32_delete(&h2s->by_id); - pool_free(pool_head_h2s, h2s); + h2s_destroy(h2s); } } } @@ -2368,9 +2369,18 @@ struct h2c *h2c = t->context; int expired = tick_is_expired(t->expire, now_ms); - if (!expired) + if (!expired && h2c) return t; + task_delete(t); + task_free(t); + + if (!h2c) { + /* resources were already deleted */ + return NULL; + } + + h2c->task = NULL; h2c_error(h2c, H2_ERR_NO_ERROR); h2_wake_some_streams(h2c, 0, 0); @@ -2387,17 +2397,12 @@ if (h2c->mbuf->o && !(h2c->flags & H2_CF_GOAWAY_FAILED) && conn_xprt_ready(h2c->conn)) h2c->conn->xprt->snd_buf(h2c->conn, h2c->mbuf, 0); - if (!eb_is_empty(&h2c->streams_by_id)) - goto wait; - - h2_release(h2c->conn); - return NULL; + /* either we can release everything now or it will be done later once + * the last stream closes. + */ + if (eb_is_empty(&h2c->streams_by_id)) + h2_release(h2c->conn); - wait: - /* the streams have been notified, we must let them finish and close */ - h2c->task = NULL; - task_delete(t); - task_free(t); return NULL; } @@ -2482,12 +2487,10 @@ /* this stream may be blocked waiting for some data to leave (possibly * an ES or RST frame), so orphan it in this case. */ - if (h2s->flags & (H2_SF_BLK_MBUSY | H2_SF_BLK_MROOM | H2_SF_BLK_MFCTL)) + if (!(cs->conn->flags & CO_FL_ERROR) && + (h2s->flags & (H2_SF_BLK_MBUSY | H2_SF_BLK_MROOM | H2_SF_BLK_MFCTL))) return; - /* the stream could be in the send list */ - LIST_DEL(&h2s->list); - if ((h2c->flags & H2_CF_DEM_BLOCK_ANY && h2s->id == h2c->dsi) || (h2c->flags & H2_CF_MUX_BLOCK_ANY && h2s->id == h2c->msi)) { /* unblock the connection if it was blocked on this @@ -2499,35 +2502,30 @@ conn_xprt_want_send(cs->conn); } - if (h2s->by_id.node.leaf_p) { - /* h2s still attached to the h2c */ - h2c_stream_close(h2c, h2s); - eb32_delete(&h2s->by_id); - - /* We don't want to close right now unless we're removing the - * last stream, and either the connection is in error, or it - * reached the ID already specified in a GOAWAY frame received - * or sent (as seen by last_sid >= 0). - */ - if (eb_is_empty(&h2c->streams_by_id) && /* don't close if streams exist */ - ((h2c->conn->flags & CO_FL_ERROR) || /* errors close immediately */ - (h2c->flags & H2_CF_GOAWAY_FAILED) || - (!h2c->mbuf->o && /* mux buffer empty, also process clean events below */ - (conn_xprt_read0_pending(h2c->conn) || - (h2c->last_sid >= 0 && h2c->max_id >= h2c->last_sid))))) { - /* no more stream will come, kill it now */ - h2_release(h2c->conn); - } - else if (h2c->task) { - if (eb_is_empty(&h2c->streams_by_id) || h2c->mbuf->o) { - h2c->task->expire = tick_add(now_ms, h2c->last_sid < 0 ? h2c->timeout : h2c->shut_timeout); - task_queue(h2c->task); - } - else - h2c->task->expire = TICK_ETERNITY; + h2s_destroy(h2s); + + /* We don't want to close right now unless we're removing the + * last stream, and either the connection is in error, or it + * reached the ID already specified in a GOAWAY frame received + * or sent (as seen by last_sid >= 0). + */ + if (eb_is_empty(&h2c->streams_by_id) && /* don't close if streams exist */ + ((h2c->conn->flags & CO_FL_ERROR) || /* errors close immediately */ + (h2c->flags & H2_CF_GOAWAY_FAILED) || + (!h2c->mbuf->o && /* mux buffer empty, also process clean events below */ + (conn_xprt_read0_pending(h2c->conn) || + (h2c->last_sid >= 0 && h2c->max_id >= h2c->last_sid))))) { + /* no more stream will come, kill it now */ + h2_release(h2c->conn); + } + else if (h2c->task) { + if (eb_is_empty(&h2c->streams_by_id) || h2c->mbuf->o) { + h2c->task->expire = tick_add(now_ms, h2c->last_sid < 0 ? h2c->timeout : h2c->shut_timeout); + task_queue(h2c->task); } + else + h2c->task->expire = TICK_ETERNITY; } - pool_free(pool_head_h2s, h2s); } static void h2_shutr(struct conn_stream *cs, enum cs_shr_mode mode) @@ -2547,17 +2545,25 @@ */ if (!(h2s->flags & H2_SF_RST_SENT) && h2s_send_rst_stream(h2s->h2c, h2s) <= 0) - return; + goto add_to_list; if (!(h2s->flags & H2_SF_OUTGOING_DATA) && !(h2s->h2c->flags & (H2_CF_GOAWAY_SENT|H2_CF_GOAWAY_FAILED)) && h2c_send_goaway_error(h2s->h2c, h2s) <= 0) - return; + goto add_to_list; if (h2s->h2c->mbuf->o && !(cs->conn->flags & CO_FL_XPRT_WR_ENA)) conn_xprt_want_send(cs->conn); - h2c_stream_close(h2s->h2c, h2s); + h2s_close(h2s); + + add_to_list: + if (LIST_ISEMPTY(&h2s->list)) { + if (h2s->flags & H2_SF_BLK_MFCTL) + LIST_ADDQ(&h2s->h2c->fctl_list, &h2s->list); + else if (h2s->flags & (H2_SF_BLK_MBUSY|H2_SF_BLK_MROOM)) + LIST_ADDQ(&h2s->h2c->send_list, &h2s->list); + } } static void h2_shutw(struct conn_stream *cs, enum cs_shw_mode mode) @@ -2572,10 +2578,10 @@ if (!(h2s->flags & (H2_SF_ES_SENT|H2_SF_RST_SENT)) && h2_send_empty_data_es(h2s) <= 0) - return; + goto add_to_list; if (h2s->st == H2_SS_HREM) - h2c_stream_close(h2s->h2c, h2s); + h2s_close(h2s); else h2s->st = H2_SS_HLOC; } else { @@ -2586,18 +2592,26 @@ */ if (!(h2s->flags & H2_SF_RST_SENT) && h2s_send_rst_stream(h2s->h2c, h2s) <= 0) - return; + goto add_to_list; if (!(h2s->flags & H2_SF_OUTGOING_DATA) && !(h2s->h2c->flags & (H2_CF_GOAWAY_SENT|H2_CF_GOAWAY_FAILED)) && h2c_send_goaway_error(h2s->h2c, h2s) <= 0) - return; + goto add_to_list; - h2c_stream_close(h2s->h2c, h2s); + h2s_close(h2s); } if (h2s->h2c->mbuf->o && !(cs->conn->flags & CO_FL_XPRT_WR_ENA)) conn_xprt_want_send(cs->conn); + + add_to_list: + if (LIST_ISEMPTY(&h2s->list)) { + if (h2s->flags & H2_SF_BLK_MFCTL) + LIST_ADDQ(&h2s->h2c->fctl_list, &h2s->list); + else if (h2s->flags & (H2_SF_BLK_MBUSY|H2_SF_BLK_MROOM)) + LIST_ADDQ(&h2s->h2c->send_list, &h2s->list); + } } /* Decode the payload of a HEADERS frame and produce the equivalent HTTP/1 @@ -3049,7 +3063,7 @@ if (h2s->st == H2_SS_OPEN) h2s->st = H2_SS_HLOC; else - h2c_stream_close(h2c, h2s); + h2s_close(h2s); } else if (h1m->status >= 100 && h1m->status < 200) { /* we'll let the caller check if it has more headers to send */ @@ -3291,7 +3305,7 @@ if (h2s->st == H2_SS_OPEN) h2s->st = H2_SS_HLOC; else - h2c_stream_close(h2c, h2s); + h2s_close(h2s); if (!(h1m->flags & H1_MF_CHNK)) { // trim any possibly pending data (eg: inconsistent content-length) @@ -3364,7 +3378,7 @@ if (h2s->st == H2_SS_ERROR || h2s->flags & H2_SF_RST_RCVD) { cs->flags |= CS_FL_ERROR; if (h2s_send_rst_stream(h2s->h2c, h2s) > 0) - h2c_stream_close(h2s->h2c, h2s); + h2s_close(h2s); } if (h2s->flags & H2_SF_BLK_SFCTL) { @@ -3372,6 +3386,12 @@ LIST_DEL(&h2s->list); LIST_INIT(&h2s->list); } + else if (LIST_ISEMPTY(&h2s->list)) { + if (h2s->flags & H2_SF_BLK_MFCTL) + LIST_ADDQ(&h2s->h2c->fctl_list, &h2s->list); + else if (h2s->flags & (H2_SF_BLK_MBUSY|H2_SF_BLK_MROOM)) + LIST_ADDQ(&h2s->h2c->send_list, &h2s->list); + } return total; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/proto_http.c new/haproxy-1.8.8/src/proto_http.c --- old/haproxy-1.8.5/src/proto_http.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/proto_http.c 2018-04-19 17:20:31.000000000 +0200 @@ -3718,9 +3718,11 @@ } path = http_get_path(txn); - url2sa(req->buf->p + msg->sl.rq.u, - path ? path - (req->buf->p + msg->sl.rq.u) : msg->sl.rq.u_l, - &conn->addr.to, NULL); + if (url2sa(req->buf->p + msg->sl.rq.u, + path ? path - (req->buf->p + msg->sl.rq.u) : msg->sl.rq.u_l, + &conn->addr.to, NULL) == -1) + goto return_bad_req; + /* if the path was found, we have to remove everything between * req->buf->p + msg->sl.rq.u and path (excluded). If it was not * found, we need to replace from req->buf->p + msg->sl.rq.u for diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/queue.c new/haproxy-1.8.8/src/queue.c --- old/haproxy-1.8.5/src/queue.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/queue.c 2018-04-19 17:20:31.000000000 +0200 @@ -181,7 +181,7 @@ HA_SPIN_UNLOCK(PROXY_LOCK, &p->lock); if (remote) - thread_want_sync(); + THREAD_WANT_SYNC(); } /* Adds the stream <strm> to the pending connection list of server <strm>->srv @@ -269,8 +269,7 @@ HA_SPIN_UNLOCK(SERVER_LOCK, &s->lock); if (remote) - thread_want_sync(); - + THREAD_WANT_SYNC(); return xferred; } @@ -308,8 +307,7 @@ HA_SPIN_UNLOCK(PROXY_LOCK, &s->proxy->lock); if (remote) - thread_want_sync(); - + THREAD_WANT_SYNC(); return xferred; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/ssl_sock.c new/haproxy-1.8.8/src/ssl_sock.c --- old/haproxy-1.8.5/src/ssl_sock.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/ssl_sock.c 2018-04-19 17:20:31.000000000 +0200 @@ -8487,6 +8487,11 @@ appctx->ctx.cli.err = err; appctx->st0 = CLI_ST_PRINT_FREE; } + else { + appctx->ctx.cli.severity = LOG_ERR; + appctx->ctx.cli.msg = "Failed to update OCSP response.\n"; + appctx->st0 = CLI_ST_PRINT; + } return 1; } appctx->ctx.cli.severity = LOG_INFO; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.8.5/src/standard.c new/haproxy-1.8.8/src/standard.c --- old/haproxy-1.8.5/src/standard.c 2018-03-23 16:58:34.000000000 +0100 +++ new/haproxy-1.8.8/src/standard.c 2018-04-19 17:20:31.000000000 +0200 @@ -629,7 +629,7 @@ * If everything is fine, NULL is returned. */ const char *invalid_prefix_char(const char *name) { - return __invalid_char(name, isalpha); + return __invalid_char(name, isalnum); } /*