From: Olivier Houchard Date: Wed, 31 Jul 2019 16:05:26 +0000 (+0200) Subject: BUG/MEDIUM: proxy: Make sure to destroy the stream on upgrade from TCP to H2 X-Git-Tag: v2.1-dev2~238 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4c18f94c11b11e4a4923892ed0fa72385ec1eb08;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/include/types/stream.h b/include/types/stream.h index eb31f068bf..90819e66df 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 fe3944e7e0..9d99ade255 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 b22eef2280..a135dcb248 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;