From 4c18f94c11b11e4a4923892ed0fa72385ec1eb08 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Wed, 31 Jul 2019 18:05:26 +0200 Subject: [PATCH] BUG/MEDIUM: proxy: Make sure to destroy the stream on upgrade from TCP to H2 In stream_set_backend(), if we have a TCP stream, and we want to upgrade it to H2 instead of attempting ot reuse the stream, just destroy the conn_stream, make sure we don't log anything about the stream, and pretend we failed setting the backend, so that the stream will get destroyed. New streams will then be created by the mux, as if the connection just happened. This fixes a crash when upgrading from TCP to H2, as the H2 mux totally ignored the conn_stream provided by the upgrade, as reported in github issue #196. This should be backported to 2.0. --- include/types/stream.h | 2 +- src/proxy.c | 15 ++++++++++++++- src/stream.c | 5 +++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/include/types/stream.h b/include/types/stream.h index eb31f068b..90819e66d 100644 --- a/include/types/stream.h +++ b/include/types/stream.h @@ -56,7 +56,7 @@ #define SF_CURR_SESS 0x00000040 /* a connection is currently being counted on the server */ /* unused: 0x00000080 */ #define SF_REDISP 0x00000100 /* set if this stream was redispatched from one server to another */ -/* unused: 0x00000200 */ +#define SF_IGNORE 0x00000200 /* The stream lead to a mux upgrade, and should be ignored */ #define SF_REDIRECTABLE 0x00000400 /* set if this stream is redirectable (GET or HEAD) */ #define SF_HTX 0x00000800 /* set if this stream is an htx stream */ diff --git a/src/proxy.c b/src/proxy.c index fe3944e7e..9d99ade25 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1457,7 +1457,20 @@ int stream_set_backend(struct stream *s, struct proxy *be) &s->si[0].wait_event); if (conn_upgrade_mux_fe(conn, cs, &s->req.buf, ist(""), PROTO_MODE_HTTP) == -1) return 0; - s->flags |= SF_HTX; + if (!strcmp(conn->mux->name, "H2")) { + /* For HTTP/2, destroy the conn_stream, + * disable logging, and pretend that we + * failed, to that the stream is + * silently destroyed. The new mux + * will create new streams. + */ + cs_destroy(cs); + si_detach_endpoint(&s->si[0]); + s->logs.logwait = 0; + s->logs.level = 0; + s->flags |= SF_IGNORE; + return 0; + } } } diff --git a/src/stream.c b/src/stream.c index b22eef228..a135dcb24 100644 --- a/src/stream.c +++ b/src/stream.c @@ -2611,7 +2611,7 @@ struct task *process_stream(struct task *t, void *context, unsigned short state) } if (likely((si_f->state != SI_ST_CLO) || !si_state_in(si_b->state, SI_SB_INI|SI_SB_CLO))) { - if ((sess->fe->options & PR_O_CONTSTATS) && (s->flags & SF_BE_ASSIGNED)) + if ((sess->fe->options & PR_O_CONTSTATS) && (s->flags & SF_BE_ASSIGNED) && !(s->flags & SF_IGNORE)) stream_process_counters(s); si_update_both(si_f, si_b); @@ -2679,7 +2679,8 @@ struct task *process_stream(struct task *t, void *context, unsigned short state) } s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now); - stream_process_counters(s); + if (!(s->flags & SF_IGNORE)) + stream_process_counters(s); if (s->txn && s->txn->status) { int n; -- 2.47.3