From 0f3835878dfa5c2bb280a5f8e8935270508b471a Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 3 Oct 2018 14:22:21 +0200 Subject: [PATCH] BUG/MEDIUM: h2: check that the connection is still valid at the end of init() Since commit 7505f94f9 ("MEDIUM: h2: Don't use a wake() method anymore."), the H2 mux's init() calls h2_process(). But this last one may detect an early error and call h2_release(), destroying the connection, and return -1. At this point we're screwed because the caller will still dereference the connection for various things ranging from the configuration of the proxy protocol header to the retries. We could simply return -1 here upon failure but that's not enough since the stream layer really needs to keep its connection structure allocated (to clean it up in session_kill_embryonic or for example because it holds the destination address to reconnect to when the connection goes to the backend). Thus the correct solution here is to only schedule a wakeup of the I/O callback so that the init succeeds, and that the connection is only handled later. No backport is needed, this is 1.9-specific. --- src/mux_h2.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/mux_h2.c b/src/mux_h2.c index b02f4c3..62eb909 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -381,6 +381,7 @@ static int h2c_frt_init(struct connection *conn) h2c->wait_list.task->process = h2_io_cb; h2c->wait_list.task->context = h2c; h2c->wait_list.wait_reason = 0; + LIST_INIT(&h2c->wait_list.list); h2c->ddht = hpack_dht_alloc(h2_settings_header_table_size); if (!h2c->ddht) @@ -414,12 +415,10 @@ static int h2c_frt_init(struct connection *conn) if (t) task_queue(t); - conn_xprt_want_recv(conn); - LIST_INIT(&h2c->wait_list.list); - /* Try to read, if nothing is available yet we'll just subscribe */ - if (h2_recv(h2c)) - h2_process(h2c); + /* prepare to read something */ + conn_xprt_want_recv(conn); + tasklet_wakeup(h2c->wait_list.task); return 0; fail: if (t) -- 1.7.10.4