Hello community, here is the log from the commit of package haproxy for openSUSE:Factory checked in at 2019-10-14 12:31:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/haproxy (Old) and /work/SRC/openSUSE:Factory/.haproxy.new.2352 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "haproxy" Mon Oct 14 12:31:19 2019 rev:75 rq:735634 version:2.0.7+git0.1909aa1e Changes: -------- --- /work/SRC/openSUSE:Factory/haproxy/haproxy.changes 2019-09-25 01:50:25.085600808 +0200 +++ /work/SRC/openSUSE:Factory/.haproxy.new.2352/haproxy.changes 2019-10-14 12:31:21.864290315 +0200 @@ -1,0 +2,26 @@ +Mon Oct 07 08:05:46 UTC 2019 - [email protected] + +- Update to version 2.0.7+git0.1909aa1e: + * [RELEASE] Released version 2.0.7 + * BUG/MEDIUM: namespace: fix fd leak in master-worker mode + * DOC: Fix documentation about the cli command to get resolver stats + * BUG/MINOR: contrib/prometheus-exporter: Return the time averages in seconds + * MINOR: stats: Add the support of float fields in stats + * MINOR: spoe: Support the async mode with several threads + * MINOR: spoe: Improve generation of the engine-id + * BUG/MEDIUM: spoe: Use a different engine-id per process + * BUG/MINOR: mux-h1: Do h2 upgrade only on the first request + * BUG/MAJOR: mux_h2: Don't consume more payload than received for skipped frames + * BUG/MINOR: mux-h2: Use the dummy error when decoding headers for a closed stream + * BUG/MEDIUM: mux-h2: don't reject valid frames on closed streams + * BUG/MEDIUM: namespace: close open namespaces during soft shutdown + * BUG/MINOR: mux-h2: do not wake up blocked streams before the mux is ready + * BUG/MEDIUM: checks: make sure the connection is ready before trying to recv + * BUG/MEDIUM: stream-int: Process connection/CS errors during synchronous sends + * BUG/MINOR: stream-int: Process connection/CS errors first in si_cs_send() + * BUG/MEDIUM: check/threads: make external checks run exclusively on thread 1 + * BUG/MAJOR: mux-h2: Handle HEADERS frames received after a RST_STREAM frame + * BUG/MINOR: mux-h2: Be sure to have a connection to unsubcribe + * BUG/MEDIUM: stick-table: Properly handle "show table" with a data type argument + +------------------------------------------------------------------- Old: ---- haproxy-2.0.6+git0.58706ab4.tar.gz New: ---- haproxy-2.0.7+git0.1909aa1e.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ haproxy.spec ++++++ --- /var/tmp/diff_new_pack.cvrGzE/_old 2019-10-14 12:31:22.872287688 +0200 +++ /var/tmp/diff_new_pack.cvrGzE/_new 2019-10-14 12:31:22.888287646 +0200 @@ -47,7 +47,7 @@ %endif Name: haproxy -Version: 2.0.6+git0.58706ab4 +Version: 2.0.7+git0.1909aa1e Release: 0 # # ++++++ _service ++++++ --- /var/tmp/diff_new_pack.cvrGzE/_old 2019-10-14 12:31:23.004287344 +0200 +++ /var/tmp/diff_new_pack.cvrGzE/_new 2019-10-14 12:31:23.008287334 +0200 @@ -6,7 +6,7 @@ <param name="versionformat">@PARENT_TAG@+git@TAG_OFFSET@.%h</param> <param name="versionrewrite-pattern">v(.*)</param> <param name="versionrewrite-replacement">\1</param> - <param name="revision">v2.0.6</param> + <param name="revision">v2.0.7</param> <param name="changesgenerate">enable</param> </service> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.cvrGzE/_old 2019-10-14 12:31:23.088287125 +0200 +++ /var/tmp/diff_new_pack.cvrGzE/_new 2019-10-14 12:31:23.092287115 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">http://git.haproxy.org/git/haproxy-2.0.git</param> - <param name="changesrevision">58706ab4bdbea3468253eddf07f2d58db43bfcb4</param> + <param name="changesrevision">1909aa1e2f34dc8aaa86c279553eec2c99c14f2e</param> </service> </servicedata> \ No newline at end of file ++++++ haproxy-2.0.6+git0.58706ab4.tar.gz -> haproxy-2.0.7+git0.1909aa1e.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/CHANGELOG new/haproxy-2.0.7+git0.1909aa1e/CHANGELOG --- old/haproxy-2.0.6+git0.58706ab4/CHANGELOG 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/CHANGELOG 2019-09-27 14:17:42.000000000 +0200 @@ -1,6 +1,28 @@ ChangeLog : =========== +2019/09/27 : 2.0.7 + - BUG/MEDIUM: stick-table: Properly handle "show table" with a data type argument + - BUG/MINOR: mux-h2: Be sure to have a connection to unsubcribe + - BUG/MAJOR: mux-h2: Handle HEADERS frames received after a RST_STREAM frame + - BUG/MEDIUM: check/threads: make external checks run exclusively on thread 1 + - BUG/MINOR: stream-int: Process connection/CS errors first in si_cs_send() + - BUG/MEDIUM: stream-int: Process connection/CS errors during synchronous sends + - BUG/MEDIUM: checks: make sure the connection is ready before trying to recv + - BUG/MINOR: mux-h2: do not wake up blocked streams before the mux is ready + - BUG/MEDIUM: namespace: close open namespaces during soft shutdown + - BUG/MEDIUM: mux-h2: don't reject valid frames on closed streams + - BUG/MINOR: mux-h2: Use the dummy error when decoding headers for a closed stream + - BUG/MAJOR: mux_h2: Don't consume more payload than received for skipped frames + - BUG/MINOR: mux-h1: Do h2 upgrade only on the first request + - BUG/MEDIUM: spoe: Use a different engine-id per process + - MINOR: spoe: Improve generation of the engine-id + - MINOR: spoe: Support the async mode with several threads + - MINOR: stats: Add the support of float fields in stats + - BUG/MINOR: contrib/prometheus-exporter: Return the time averages in seconds + - DOC: Fix documentation about the cli command to get resolver stats + - BUG/MEDIUM: namespace: fix fd leak in master-worker mode + 2019/09/13 : 2.0.6 - MINOR: debug: indicate the applet name when the task is task_run_applet() - MINOR: tools: add append_prefixed_str() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/VERDATE new/haproxy-2.0.7+git0.1909aa1e/VERDATE --- old/haproxy-2.0.6+git0.58706ab4/VERDATE 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/VERDATE 2019-09-27 14:17:42.000000000 +0200 @@ -1,2 +1,2 @@ $Format:%ci$ -2019/09/13 +2019/09/27 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/VERSION new/haproxy-2.0.7+git0.1909aa1e/VERSION --- old/haproxy-2.0.6+git0.58706ab4/VERSION 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/VERSION 2019-09-27 14:17:42.000000000 +0200 @@ -1 +1 @@ -2.0.6 +2.0.7 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/contrib/prometheus-exporter/service-prometheus.c new/haproxy-2.0.7+git0.1909aa1e/contrib/prometheus-exporter/service-prometheus.c --- old/haproxy-2.0.6+git0.58706ab4/contrib/prometheus-exporter/service-prometheus.c 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/contrib/prometheus-exporter/service-prometheus.c 2019-09-27 14:17:42.000000000 +0200 @@ -1079,6 +1079,7 @@ case FF_U32: ret = chunk_appendf(out, "%u\n", f->u.u32); break; case FF_S64: ret = chunk_appendf(out, "%lld\n", (long long)f->u.s64); break; case FF_U64: ret = chunk_appendf(out, "%llu\n", (unsigned long long)f->u.u64); break; + case FF_FLT: ret = chunk_appendf(out, "%f\n", f->u.flt); break; case FF_STR: ret = chunk_strcat(out, "Nan\n"); break; default: ret = chunk_strcat(out, "Nan\n"); break; } @@ -1607,6 +1608,7 @@ size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx)); int ret = 1; uint32_t weight; + double secs; while (appctx->st2 && appctx->st2 < ST_F_TOTAL_FIELDS) { while (appctx->ctx.stats.px) { @@ -1657,16 +1659,20 @@ metric = mkf_u64(FN_COUNTER, px->be_counters.bytes_out); break; case ST_F_QTIME: - metric = mkf_u32(FN_AVG, swrate_avg(px->be_counters.q_time, TIME_STATS_SAMPLES)); + secs = (double)swrate_avg(px->be_counters.q_time, TIME_STATS_SAMPLES) / 1000.0; + metric = mkf_flt(FN_AVG, secs); break; case ST_F_CTIME: - metric = mkf_u32(FN_AVG, swrate_avg(px->be_counters.c_time, TIME_STATS_SAMPLES)); + secs = (double)swrate_avg(px->be_counters.c_time, TIME_STATS_SAMPLES) / 1000.0; + metric = mkf_flt(FN_AVG, secs); break; case ST_F_RTIME: - metric = mkf_u32(FN_AVG, swrate_avg(px->be_counters.d_time, TIME_STATS_SAMPLES)); + secs = (double)swrate_avg(px->be_counters.d_time, TIME_STATS_SAMPLES) / 1000.0; + metric = mkf_flt(FN_AVG, secs); break; case ST_F_TTIME: - metric = mkf_u32(FN_AVG, swrate_avg(px->be_counters.t_time, TIME_STATS_SAMPLES)); + secs = (double)swrate_avg(px->be_counters.t_time, TIME_STATS_SAMPLES) / 1000.0; + metric = mkf_flt(FN_AVG, secs); break; case ST_F_DREQ: metric = mkf_u64(FN_COUNTER, px->be_counters.denied_req); @@ -1828,6 +1834,7 @@ size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx)); int ret = 1; uint32_t weight; + double secs; while (appctx->st2 && appctx->st2 < ST_F_TOTAL_FIELDS) { while (appctx->ctx.stats.px) { @@ -1878,16 +1885,20 @@ metric = mkf_u64(FN_COUNTER, sv->counters.bytes_out); break; case ST_F_QTIME: - metric = mkf_u32(FN_AVG, swrate_avg(sv->counters.q_time, TIME_STATS_SAMPLES)); + secs = (double)swrate_avg(sv->counters.q_time, TIME_STATS_SAMPLES) / 1000.0; + metric = mkf_flt(FN_AVG, secs); break; case ST_F_CTIME: - metric = mkf_u32(FN_AVG, swrate_avg(sv->counters.c_time, TIME_STATS_SAMPLES)); + secs = (double)swrate_avg(sv->counters.c_time, TIME_STATS_SAMPLES) / 1000.0; + metric = mkf_flt(FN_AVG, secs); break; case ST_F_RTIME: - metric = mkf_u32(FN_AVG, swrate_avg(sv->counters.d_time, TIME_STATS_SAMPLES)); + secs = (double)swrate_avg(sv->counters.d_time, TIME_STATS_SAMPLES) / 1000.0; + metric = mkf_flt(FN_AVG, secs); break; case ST_F_TTIME: - metric = mkf_u32(FN_AVG, swrate_avg(sv->counters.t_time, TIME_STATS_SAMPLES)); + secs = (double)swrate_avg(sv->counters.t_time, TIME_STATS_SAMPLES) / 1000.0; + metric = mkf_flt(FN_AVG, secs); break; case ST_F_CONNECT: metric = mkf_u64(FN_COUNTER, sv->counters.connect); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/doc/configuration.txt new/haproxy-2.0.7+git0.1909aa1e/doc/configuration.txt --- old/haproxy-2.0.6+git0.58706ab4/doc/configuration.txt 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/doc/configuration.txt 2019-09-27 14:17:42.000000000 +0200 @@ -4,7 +4,7 @@ ---------------------- version 2.0 willy tarreau - 2019/09/13 + 2019/09/27 This document covers the configuration language as implemented in the version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/doc/management.txt new/haproxy-2.0.7+git0.1909aa1e/doc/management.txt --- old/haproxy-2.0.6+git0.58706ab4/doc/management.txt 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/doc/management.txt 2019-09-27 14:17:42.000000000 +0200 @@ -2425,7 +2425,7 @@ $ echo "show stat json" | socat /var/run/haproxy.sock stdio | \ python -m json.tool -show stat resolvers [<resolvers section id>] +show resolvers [<resolvers section id>] Dump statistics for the given resolvers section, or all resolvers sections if no section is supplied. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/include/proto/stats.h new/haproxy-2.0.7+git0.1909aa1e/include/proto/stats.h --- old/haproxy-2.0.6+git0.58706ab4/include/proto/stats.h 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/include/proto/stats.h 2019-09-27 14:17:42.000000000 +0200 @@ -84,6 +84,12 @@ return f; } +static inline struct field mkf_flt(uint32_t type, double value) +{ + struct field f = { .type = FF_FLT | type, .u.flt = value }; + return f; +} + extern const char *stat_status_codes[]; /* These two structs contains all field names according with diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/include/types/spoe.h new/haproxy-2.0.7+git0.1909aa1e/include/types/spoe.h --- old/haproxy-2.0.6+git0.58706ab4/include/types/spoe.h 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/include/types/spoe.h 2019-09-27 14:17:42.000000000 +0200 @@ -244,7 +244,6 @@ } timeout; /* Config info */ - char *engine_id; /* engine-id string */ char *var_pfx; /* Prefix used for vars set by the agent */ char *var_on_error; /* Variable to set when an error occurred, in the TXN scope */ char *var_t_process; /* Variable to set to report the processing time of the last event/group, in the TXN scope */ @@ -264,6 +263,7 @@ /* running info */ struct { + char *engine_id; /* engine-id string */ unsigned int frame_size; /* current maximum frame size, only used to encode messages */ unsigned int processing; struct freq_ctr processing_per_sec; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/include/types/stats.h new/haproxy-2.0.7+git0.1909aa1e/include/types/stats.h --- old/haproxy-2.0.6+git0.58706ab4/include/types/stats.h 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/include/types/stats.h 2019-09-27 14:17:42.000000000 +0200 @@ -195,6 +195,7 @@ FF_S64 = 0x00000003, FF_U64 = 0x00000004, FF_STR = 0x00000005, + FF_FLT = 0x00000006, FF_MASK = 0x000000FF, }; @@ -242,6 +243,7 @@ uint32_t u32; /* FF_U32 */ int64_t s64; /* FF_S64 */ uint64_t u64; /* FF_U64 */ + double flt; /* FF_FLT */ const char *str; /* FF_STR */ } u; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/src/checks.c new/haproxy-2.0.7+git0.1909aa1e/src/checks.c --- old/haproxy-2.0.6+git0.58706ab4/src/checks.c 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/src/checks.c 2019-09-27 14:17:42.000000000 +0200 @@ -875,6 +875,9 @@ } } + /* the rest of the code below expects the connection to be ready! */ + if (!(conn->flags & CO_FL_CONNECTED) && !done) + goto wait_more_data; /* Intermediate or complete response received. * Terminate string in b_head(&check->bi) buffer. @@ -2175,7 +2178,7 @@ /* a success was detected */ check_notify_success(check); } - task_set_affinity(t, MAX_THREADS_MASK); + task_set_affinity(t, 1); check->state &= ~CHK_ST_INPROGRESS; pid_list_del(check->curpid); @@ -2423,8 +2426,13 @@ int nbcheck, int srvpos) { struct task *t; + unsigned long thread_mask = MAX_THREADS_MASK; + + if (check->type == PR_O2_EXT_CHK) + thread_mask = 1; + /* task for the check */ - if ((t = task_new(MAX_THREADS_MASK)) == NULL) { + if ((t = task_new(thread_mask)) == NULL) { ha_alert("Starting [%s:%s] check: out of memory.\n", check->server->proxy->id, check->server->id); return 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/src/flt_spoe.c new/haproxy-2.0.7+git0.1909aa1e/src/flt_spoe.c --- old/haproxy-2.0.6+git0.58706ab4/src/flt_spoe.c 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/src/flt_spoe.c 2019-09-27 14:17:42.000000000 +0200 @@ -172,7 +172,6 @@ free(agent->id); free(agent->conf.file); free(agent->var_pfx); - free(agent->engine_id); free(agent->var_on_error); free(agent->var_t_process); free(agent->var_t_total); @@ -185,8 +184,10 @@ spoe_release_group(grp); } if (agent->rt) { - for (i = 0; i < global.nbthread; ++i) + for (i = 0; i < global.nbthread; ++i) { + free(agent->rt[i].engine_id); HA_SPIN_DESTROY(&agent->rt[i].lock); + } } free(agent->rt); free(agent); @@ -256,30 +257,32 @@ static char * generate_pseudo_uuid() { - static int init = 0; - - const char uuid_fmt[] = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"; - const char uuid_chr[] = "0123456789ABCDEF-"; char *uuid; - int i; + uint32_t rnd[4] = { 0, 0, 0, 0 }; + uint64_t last = 0; + int byte = 0; + uint8_t bits = 0; + unsigned int rand_max_bits = my_flsl(RAND_MAX); - if ((uuid = calloc(1, sizeof(uuid_fmt))) == NULL) + if ((uuid = calloc(1, 37)) == NULL) return NULL; - if (!init) { - srand(now_ms); - init = 1; - } - - for (i = 0; i < sizeof(uuid_fmt)-1; i++) { - int r = rand () % 16; - - switch (uuid_fmt[i]) { - case 'x' : uuid[i] = uuid_chr[r]; break; - case 'y' : uuid[i] = uuid_chr[(r & 0x03) | 0x08]; break; - default : uuid[i] = uuid_fmt[i]; break; - } - } + while (byte < 4) { + while (bits < 32) { + last |= (uint64_t)random() << bits; + bits += rand_max_bits; + } + rnd[byte++] = last; + last >>= 32u; + bits -= 32; + } + snprintf(uuid, 36, "%8.8x-%4.4x-%4.4x-%4.4x-%12.12llx", + rnd[0], + rnd[1] & 0xFFFF, + ((rnd[1] >> 16u) & 0xFFF) | 0x4000, // highest 4 bits indicate the uuid version + (rnd[2] & 0x3FFF) | 0x8000, // the highest 2 bits indicate the UUID variant (10), + (long long)((rnd[2] >> 14u) | ((uint64_t) rnd[3] << 18u)) & 0xFFFFFFFFFFFFull + ); return uuid; } @@ -458,14 +461,14 @@ goto too_big; /* (optionnal) "engine-id" K/V item, if present */ - if (agent != NULL && agent->engine_id != NULL) { + if (agent != NULL && agent->rt[tid].engine_id != NULL) { sz = SLEN(ENGINE_ID_KEY); if (spoe_encode_buffer(ENGINE_ID_KEY, sz, &p, end) == -1) goto too_big; *p++ = SPOE_DATA_T_STR; - sz = strlen(agent->engine_id); - if (spoe_encode_buffer(agent->engine_id, sz, &p, end) == -1) + sz = strlen(agent->rt[tid].engine_id); + if (spoe_encode_buffer(agent->rt[tid].engine_id, sz, &p, end) == -1) goto too_big; } @@ -3087,16 +3090,13 @@ return 1; } - /* finish per-thread agent initialization */ - if (global.nbthread == 1) - conf->agent->flags |= SPOE_FL_ASYNC; - if ((conf->agent->rt = calloc(global.nbthread, sizeof(*conf->agent->rt))) == NULL) { ha_alert("Proxy %s : out of memory initializing SPOE agent '%s' declared at %s:%d.\n", px->id, conf->agent->id, conf->agent->conf.file, conf->agent->conf.line); return 1; } for (i = 0; i < global.nbthread; ++i) { + conf->agent->rt[i].engine_id = NULL; conf->agent->rt[i].frame_size = conf->agent->max_frame_size; conf->agent->rt[i].processing = 0; LIST_INIT(&conf->agent->rt[i].applets); @@ -3111,6 +3111,24 @@ return 0; } +/* Initializes the SPOE filter for a proxy for a specific thread. + * Returns a negative value if an error occurs. */ +static int +spoe_init_per_thread(struct proxy *p, struct flt_conf *fconf) +{ + struct spoe_config *conf = fconf->conf; + struct spoe_agent *agent = conf->agent; + + /* Use a != seed per process */ + if (relative_pid > 1 && tid == 0) + srandom(now_ms * pid); + + agent->rt[tid].engine_id = generate_pseudo_uuid(); + if (agent->rt[tid].engine_id == NULL) + return -1; + return 0; +} + /************************************************************************** * Hooks attached to a stream *************************************************************************/ @@ -3309,6 +3327,7 @@ .init = spoe_init, .deinit = spoe_deinit, .check = spoe_check, + .init_per_thread = spoe_init_per_thread, /* Handle start/stop of SPOE */ .attach = spoe_start, @@ -3374,12 +3393,11 @@ curagent->timeout.idle = TICK_ETERNITY; curagent->timeout.processing = TICK_ETERNITY; - curagent->engine_id = NULL; curagent->var_pfx = NULL; curagent->var_on_error = NULL; curagent->var_t_process = NULL; curagent->var_t_total = NULL; - curagent->flags = (SPOE_FL_PIPELINING | SPOE_FL_SND_FRAGMENTATION); + curagent->flags = (SPOE_FL_ASYNC | SPOE_FL_PIPELINING | SPOE_FL_SND_FRAGMENTATION); curagent->cps_max = 0; curagent->eps_max = 0; curagent->max_frame_size = MAX_FRAME_SIZE; @@ -3524,15 +3542,8 @@ goto out; if (kwm == 1) curagent->flags &= ~SPOE_FL_ASYNC; - else { - if (global.nbthread == 1) - curagent->flags |= SPOE_FL_ASYNC; - else { - ha_warning("parsing [%s:%d] Async option is not supported with threads.\n", - file, linenum); - err_code |= ERR_WARN; - } - } + else + curagent->flags |= SPOE_FL_ASYNC; goto out; } else if (!strcmp(args[1], "send-frag-payload")) { @@ -4177,8 +4188,6 @@ } curagent->var_pfx = strdup(curagent->id); } - if (curagent->engine_id == NULL) - curagent->engine_id = generate_pseudo_uuid(); if (curagent->var_on_error) { struct arg arg; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/src/mux_h1.c new/haproxy-2.0.7+git0.1909aa1e/src/mux_h1.c --- old/haproxy-2.0.6+git0.58706ab4/src/mux_h1.c 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/src/mux_h1.c 2019-09-27 14:17:42.000000000 +0200 @@ -989,7 +989,7 @@ if (b_head(buf) + b_data(buf) > b_wrap(buf)) b_slow_realign(buf, trash.area, 0); - if (!(h1m->flags & H1_MF_RESP)) { + if (!(h1s->flags & H1S_F_NOT_FIRST) && !(h1m->flags & H1_MF_RESP)) { /* Try to match H2 preface before parsing the request headers. */ ret = b_isteq(buf, 0, b_data(buf), ist(H2_CONN_PREFACE)); if (ret > 0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/src/mux_h2.c new/haproxy-2.0.7+git0.1909aa1e/src/mux_h2.c --- old/haproxy-2.0.6+git0.58706ab4/src/mux_h2.c 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/src/mux_h2.c 2019-09-27 14:17:42.000000000 +0200 @@ -677,9 +677,9 @@ } if (h2c->wait_event.tasklet) tasklet_free(h2c->wait_event.tasklet); - if (h2c->wait_event.events != 0) + if (conn && h2c->wait_event.events != 0) conn->xprt->unsubscribe(conn, conn->xprt_ctx, h2c->wait_event.events, - &h2c->wait_event); + &h2c->wait_event); pool_free(pool_head_h2c, h2c); } @@ -2106,6 +2106,9 @@ */ static struct h2s *h2c_bck_handle_headers(struct h2c *h2c, struct h2s *h2s) { + struct buffer rxbuf = BUF_NULL; + unsigned long long body_len = 0; + uint32_t flags = 0; int error; if (!b_size(&h2c->dbuf)) @@ -2114,7 +2117,18 @@ if (b_data(&h2c->dbuf) < h2c->dfl && !b_full(&h2c->dbuf)) return NULL; // incomplete frame - error = h2c_decode_headers(h2c, &h2s->rxbuf, &h2s->flags, &h2s->body_len); + if (h2s->st != H2_SS_CLOSED) { + error = h2c_decode_headers(h2c, &h2s->rxbuf, &h2s->flags, &h2s->body_len); + } + else { + /* the connection was already killed by an RST, let's consume + * the data and send another RST. + */ + error = h2c_decode_headers(h2c, &rxbuf, &flags, &body_len); + h2s = (struct h2s*)h2_error_stream; + h2c->st0 = H2_CS_FRAME_E; + goto send_rst; + } /* unrecoverable error ? */ if (h2c->st0 >= H2_CS_ERROR) @@ -2150,6 +2164,15 @@ } return h2s; + + send_rst: + /* make the demux send an RST for the current stream. We may only + * do this if we're certain that the HEADERS frame was properly + * decompressed so that the HPACK decoder is still kept up to date. + */ + h2_release_buf(h2c, &rxbuf); + h2c->st0 = H2_CS_FRAME_E; + return h2s; } /* processes a DATA frame. Returns > 0 on success or zero on missing data. @@ -2459,7 +2482,8 @@ goto strm_err; } - if (h2s->flags & H2_SF_RST_RCVD && h2_ft_bit(h2c->dft) & H2_FT_HDR_MASK) { + if (h2s->flags & H2_SF_RST_RCVD && + !(h2_ft_bit(h2c->dft) & (H2_FT_HDR_MASK | H2_FT_RST_STREAM_BIT | H2_FT_PRIORITY_BIT | H2_FT_WINDOW_UPDATE_BIT))) { /* RFC7540#5.1:closed: an endpoint that * receives any frame other than PRIORITY after * receiving a RST_STREAM MUST treat that as a @@ -2474,6 +2498,10 @@ * happen with request trailers received after sending an * RST_STREAM, or with header/trailers responses received after * sending RST_STREAM (aborted stream). + * + * In addition, since our CLOSED streams always carry the + * RST_RCVD bit, we don't want to accidently catch valid + * frames for a closed stream, i.e. RST/PRIO/WU. */ h2s_error(h2s, H2_ERR_STREAM_CLOSED); h2c->st0 = H2_CS_FRAME_E; @@ -2620,8 +2648,11 @@ break; if (h2c->st0 != H2_CS_FRAME_H) { - b_del(&h2c->dbuf, h2c->dfl); - h2c->st0 = H2_CS_FRAME_H; + ret = MIN(b_data(&h2c->dbuf), h2c->dfl); + b_del(&h2c->dbuf, ret); + h2c->dfl -= ret; + if (!h2c->dfl) + h2c->st0 = H2_CS_FRAME_H; } } @@ -2892,7 +2923,7 @@ /* We're not full anymore, so we can wake any task that are waiting * for us. */ - if (!(h2c->flags & (H2_CF_MUX_MFULL | H2_CF_DEM_MROOM))) { + if (!(h2c->flags & (H2_CF_MUX_MFULL | H2_CF_DEM_MROOM)) && h2c->st0 >= H2_CS_FRAME_H) { struct h2s *h2s; list_for_each_entry(h2s, &h2c->send_list, list) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/src/namespace.c new/haproxy-2.0.7+git0.1909aa1e/src/namespace.c --- old/haproxy-2.0.6+git0.58706ab4/src/namespace.c 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/src/namespace.c 2019-09-27 14:17:42.000000000 +0200 @@ -15,6 +15,7 @@ #include <common/hash.h> #include <common/errors.h> #include <proto/log.h> +#include <proto/signal.h> #include <types/global.h> /* Opens the namespace <ns_name> and returns the FD or -1 in case of error @@ -24,7 +25,7 @@ { if (chunk_printf(&trash, "/var/run/netns/%s", ns_name) < 0) return -1; - return open(trash.area, O_RDONLY); + return open(trash.area, O_RDONLY | O_CLOEXEC); } static int default_namespace = -1; @@ -33,12 +34,30 @@ { if (chunk_printf(&trash, "/proc/%d/ns/net", getpid()) < 0) return -1; - default_namespace = open(trash.area, O_RDONLY); + default_namespace = open(trash.area, O_RDONLY | O_CLOEXEC); return default_namespace; } static struct eb_root namespace_tree_root = EB_ROOT; +static void netns_sig_stop(struct sig_handler *sh) +{ + struct ebpt_node *node, *next; + struct netns_entry *entry; + + /* close namespace file descriptors and remove registered namespaces from the + * tree when stopping */ + node = ebpt_first(&namespace_tree_root); + while (node) { + next = ebpt_next(node); + ebpt_delete(node); + entry = container_of(node, struct netns_entry, node); + free(entry->node.key); + close(entry->fd); + node = next; + } +} + int netns_init(void) { int err_code = 0; @@ -55,6 +74,8 @@ } } + signal_register_fct(0, netns_sig_stop, 0); + return err_code; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/src/stats.c new/haproxy-2.0.7+git0.1909aa1e/src/stats.c --- old/haproxy-2.0.6+git0.58706ab4/src/stats.c 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/src/stats.c 2019-09-27 14:17:42.000000000 +0200 @@ -341,6 +341,7 @@ case FF_U32: return chunk_appendf(out, "%u", f->u.u32); case FF_S64: return chunk_appendf(out, "%lld", (long long)f->u.s64); case FF_U64: return chunk_appendf(out, "%llu", (unsigned long long)f->u.u64); + case FF_FLT: return chunk_appendf(out, "%f", f->u.flt); case FF_STR: return csv_enc_append(field_str(f, 0), 1, out) != NULL; default: return chunk_appendf(out, "[INCORRECT_FIELD_TYPE_%08x]", f->type); } @@ -358,6 +359,7 @@ case FF_U32: return chunk_appendf(out, "u32:%u", f->u.u32); case FF_S64: return chunk_appendf(out, "s64:%lld", (long long)f->u.s64); case FF_U64: return chunk_appendf(out, "u64:%llu", (unsigned long long)f->u.u64); + case FF_FLT: return chunk_appendf(out, "flt:%f", f->u.flt); case FF_STR: return chunk_appendf(out, "str:%s", field_str(f, 0)); default: return chunk_appendf(out, "%08x:?", f->type); } @@ -397,6 +399,8 @@ type = "\"u64\""; snprintf(buf, sizeof(buf), "%llu", (unsigned long long) f->u.u64); + case FF_FLT: type = "\"flt\""; + snprintf(buf, sizeof(buf), "%f", f->u.flt); break; case FF_STR: type = "\"str\""; value = field_str(f, 0); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/src/stick_table.c new/haproxy-2.0.7+git0.1909aa1e/src/stick_table.c --- old/haproxy-2.0.6+git0.58706ab4/src/stick_table.c 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/src/stick_table.c 2019-09-27 14:17:42.000000000 +0200 @@ -3601,8 +3601,7 @@ return 1; } - if (!((struct proxy *)appctx->ctx.table.target)->table || - !((struct proxy *)appctx->ctx.table.target)->table->data_ofs[appctx->ctx.table.data_type]) { + if (!((struct stktable *)appctx->ctx.table.target)->data_ofs[appctx->ctx.table.data_type]) { appctx->ctx.cli.severity = LOG_ERR; appctx->ctx.cli.msg = "Data type not stored in this table\n"; appctx->st0 = CLI_ST_PRINT; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-2.0.6+git0.58706ab4/src/stream_interface.c new/haproxy-2.0.7+git0.1909aa1e/src/stream_interface.c --- old/haproxy-2.0.6+git0.58706ab4/src/stream_interface.c 2019-09-13 13:46:44.000000000 +0200 +++ new/haproxy-2.0.7+git0.1909aa1e/src/stream_interface.c 2019-09-27 14:17:42.000000000 +0200 @@ -652,10 +652,6 @@ int ret; int did_send = 0; - /* We're already waiting to be able to send, give up */ - if (si->wait_event.events & SUB_RETRY_SEND) - return 0; - if (conn->flags & CO_FL_ERROR || cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING)) { /* We're probably there because the tasklet was woken up, * but process_stream() ran before, detected there were an @@ -669,6 +665,10 @@ return 1; } + /* We're already waiting to be able to send, give up */ + if (si->wait_event.events & SUB_RETRY_SEND) + return 0; + /* we might have been called just after an asynchronous shutw */ if (conn->flags & CO_FL_SOCK_WR_SH || oc->flags & CF_SHUTW) return 1; @@ -922,12 +922,6 @@ if (!cs) return; - if (cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING)) - return; - - if (cs->conn->flags & CO_FL_ERROR) - return; - si_cs_send(cs); }
