Hi Cyril, On Tue, Aug 21, 2018 at 12:51:13PM +0200, Cyril Bonté wrote: > Hi Willy, > > I'm afraid there's still some issues with HTTP/2 in the current dev branch :-( > > This morning, I've upgraded a test server and discovered that some HTTPS > sites did not work anymore (content hangs and is not sent to the client), > I've also noticed some segfaults in haproxy. > As this is a test server that I've used for several years with haproxy, the > configuration begins to be quite ugly, it won't be helpful to provide it in > its current state. >
I think I figured those out, well at least I don't have hangs anymore, and I think I understood those segfaults. The attached patchset should do the trick. Willy, those should be mergeable. Thanks ! Olivier
>From 159f4653cffdd26fb62a26d047ac3f87f7506e59 Mon Sep 17 00:00:00 2001 From: Olivier Houchard <ohouch...@haproxy.com> Date: Tue, 21 Aug 2018 14:25:52 +0200 Subject: [PATCH 1/5] BUG/MEDIUM: streams: Don't forget to remove the si from the wait list. When freeing the stream, make sure we remove the stream interfaces from the wait lists, in case it was in there. --- src/stream.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/stream.c b/src/stream.c index bc0f1ac7..0f2ccf01 100644 --- a/src/stream.c +++ b/src/stream.c @@ -409,7 +409,9 @@ static void stream_free(struct stream *s) session_free(sess); tasklet_free(s->si[0].wait_list.task); + LIST_DEL(&s->si[0].wait_list.list); tasklet_free(s->si[1].wait_list.task); + LIST_DEL(&s->si[1].wait_list.list); pool_free(pool_head_stream, s); /* We may want to free the maximum amount of pools if the proxy is stopping */ -- 2.14.3
>From 3c93f5ad9f6dd14114c01217a11d56455c1fe62d Mon Sep 17 00:00:00 2001 From: Olivier Houchard <ohouch...@haproxy.com> Date: Fri, 17 Aug 2018 18:57:51 +0200 Subject: [PATCH 2/5] BUG/MEDIUM: tasklets: Add the thread as active when waking a tasklet. Set the flag for the current thread in active_threads_mask when waking a tasklet, or we will never run it if no tasks are available. --- include/proto/task.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/proto/task.h b/include/proto/task.h index 13398c53..eef4ded4 100644 --- a/include/proto/task.h +++ b/include/proto/task.h @@ -226,6 +226,7 @@ static inline void tasklet_wakeup(struct tasklet *tl) return; LIST_ADDQ(&task_list[tid], &tl->list); task_list_size[tid]++; + HA_ATOMIC_OR(&active_tasks_mask, tid_bit); HA_ATOMIC_ADD(&tasks_run_queue, 1); } -- 2.14.3
>From 722665b5f60b65ad0eb035b6dd2162062dcbf42f Mon Sep 17 00:00:00 2001 From: Olivier Houchard <ohouch...@haproxy.com> Date: Tue, 21 Aug 2018 15:59:43 +0200 Subject: [PATCH 3/5] BUG/MEDIUM: Check if the conn_stream exist in si_cs_io_cb. It is possible that the conn_stream gets detached from the stream_interface, and as it subscribed to the wait list, si_cs_io_cb() gets called anyway, so make sure we have a conn_stream before attempting to send more data. --- src/stream_interface.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/stream_interface.c b/src/stream_interface.c index 4b5b760c..52aa7c43 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -760,8 +760,12 @@ wake_others: struct task *si_cs_io_cb(struct task *t, void *ctx, unsigned short state) { struct stream_interface *si = ctx; + struct conn_stream *cs = objt_cs(si->end); + + if (!cs) + return NULL; if (!(si->wait_list.wait_reason & SUB_CAN_SEND)) - si_cs_send(__objt_cs(si->end)); + si_cs_send(cs); return (NULL); } -- 2.14.3
>From bee74b66b702126dd7bd808d0f4037ba885441a2 Mon Sep 17 00:00:00 2001 From: Olivier Houchard <ohouch...@haproxy.com> Date: Tue, 21 Aug 2018 16:36:10 +0200 Subject: [PATCH 4/5] BUG/MEDIUM: H2: Activate polling after successful h2_snd_buf(). Make sure h2_send() is called after h2_snd_buf() by activating polling. --- src/mux_h2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mux_h2.c b/src/mux_h2.c index 4a3150a2..7824cfe4 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -3531,6 +3531,8 @@ static size_t h2_snd_buf(struct conn_stream *cs, struct buffer *buf, size_t coun } b_del(buf, total); + if (total > 0) + conn_xprt_want_send(h2s->h2c->conn); return total; } -- 2.14.3
>From 64220c175bdc43fc82efc73c633be3b0212ab3e2 Mon Sep 17 00:00:00 2001 From: Olivier Houchard <ohouch...@haproxy.com> Date: Tue, 21 Aug 2018 16:37:06 +0200 Subject: [PATCH 5/5] BUG/MEDIUM: stream_interface: Call the wake callback after sending. If we subscribed to send, and the callback is called, call the wake callback after, so that process_stream() may be woken up if needed. --- src/stream_interface.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stream_interface.c b/src/stream_interface.c index 52aa7c43..51f2300d 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -764,8 +764,10 @@ struct task *si_cs_io_cb(struct task *t, void *ctx, unsigned short state) if (!cs) return NULL; - if (!(si->wait_list.wait_reason & SUB_CAN_SEND)) + if (!(si->wait_list.wait_reason & SUB_CAN_SEND)) { si_cs_send(cs); + si_cs_wake_cb(cs); + } return (NULL); } -- 2.14.3