From e2a74327fdca52a13bb4ad1b4898218a56d4a2e4 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Mon, 19 Sep 2016 16:21:42 +0000 Subject: [PATCH] mod_http2: rest of the fix for output blockage git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1761477 13f79535-47bb-0310-9956-ffa450edef68 --- modules/http2/h2_bucket_beam.c | 54 +++++++++++++++++++--------------- modules/http2/h2_mplx.c | 2 +- modules/http2/h2_mplx.h | 2 ++ modules/http2/h2_stream.c | 3 ++ modules/http2/h2_task.c | 15 ++++++++-- 5 files changed, 50 insertions(+), 26 deletions(-) diff --git a/modules/http2/h2_bucket_beam.c b/modules/http2/h2_bucket_beam.c index 1338ba68b0..b1d698e796 100644 --- a/modules/http2/h2_bucket_beam.c +++ b/modules/http2/h2_bucket_beam.c @@ -223,6 +223,28 @@ static void leave_yellow(h2_bucket_beam *beam, h2_beam_lock *pbl) } } +static void report_consumption(h2_bucket_beam *beam, int force) +{ + if (force || beam->received_bytes != beam->reported_consumed_bytes) { + if (beam->consumed_fn) { + beam->consumed_fn(beam->consumed_ctx, beam, beam->received_bytes + - beam->reported_consumed_bytes); + } + beam->reported_consumed_bytes = beam->received_bytes; + } +} + +static void report_production(h2_bucket_beam *beam, int force) +{ + if (force || beam->sent_bytes != beam->reported_produced_bytes) { + if (beam->produced_fn) { + beam->produced_fn(beam->produced_ctx, beam, beam->sent_bytes + - beam->reported_produced_bytes); + } + beam->reported_produced_bytes = beam->sent_bytes; + } +} + static apr_off_t calc_buffered(h2_bucket_beam *beam) { apr_off_t len = 0; @@ -279,7 +301,9 @@ static apr_status_t r_wait_space(h2_bucket_beam *beam, apr_read_type_e block, *premain = calc_space_left(beam); while (!beam->aborted && *premain <= 0 && (block == APR_BLOCK_READ) && pbl->mutex) { - apr_status_t status = wait_cond(beam, pbl->mutex); + apr_status_t status; + report_production(beam, 1); + status = wait_cond(beam, pbl->mutex); if (APR_STATUS_IS_TIMEUP(status)) { return status; } @@ -356,28 +380,6 @@ static void h2_beam_emitted(h2_bucket_beam *beam, h2_beam_proxy *proxy) } } -static void report_consumption(h2_bucket_beam *beam, int force) -{ - if (force || beam->received_bytes != beam->reported_consumed_bytes) { - if (beam->consumed_fn) { - beam->consumed_fn(beam->consumed_ctx, beam, beam->received_bytes - - beam->reported_consumed_bytes); - } - beam->reported_consumed_bytes = beam->received_bytes; - } -} - -static void report_production(h2_bucket_beam *beam, int force) -{ - if (force || beam->sent_bytes != beam->reported_produced_bytes) { - if (beam->produced_fn) { - beam->produced_fn(beam->produced_ctx, beam, beam->sent_bytes - - beam->reported_produced_bytes); - } - beam->reported_produced_bytes = beam->sent_bytes; - } -} - static void h2_blist_cleanup(h2_blist *bl) { apr_bucket *e; @@ -877,6 +879,9 @@ transfer: } if (transferred) { + if (beam->m_cond) { + apr_thread_cond_broadcast(beam->m_cond); + } status = APR_SUCCESS; } else if (beam->closed) { @@ -890,6 +895,9 @@ transfer: goto transfer; } else { + if (beam->m_cond) { + apr_thread_cond_broadcast(beam->m_cond); + } status = APR_EAGAIN; } leave: diff --git a/modules/http2/h2_mplx.c b/modules/http2/h2_mplx.c index ea574abc4d..dd0f0fdd29 100644 --- a/modules/http2/h2_mplx.c +++ b/modules/http2/h2_mplx.c @@ -545,7 +545,7 @@ static int task_abort_connection(void *ctx, void *val) if (task->input.beam) { h2_beam_abort(task->input.beam); } - if (task->output.beam) { + if (task->worker_started && !task->worker_done && task->output.beam) { h2_beam_abort(task->output.beam); } return 1; diff --git a/modules/http2/h2_mplx.h b/modules/http2/h2_mplx.h index 4af0ba3c13..b2873e8827 100644 --- a/modules/http2/h2_mplx.h +++ b/modules/http2/h2_mplx.h @@ -158,6 +158,8 @@ void h2_mplx_task_done(h2_mplx *m, struct h2_task *task, struct h2_task **ptask) */ apr_uint32_t h2_mplx_shutdown(h2_mplx *m); +int h2_mplx_is_busy(h2_mplx *m); + /******************************************************************************* * IO lifetime of streams. ******************************************************************************/ diff --git a/modules/http2/h2_stream.c b/modules/http2/h2_stream.c index 7004647c0e..02e1a12741 100644 --- a/modules/http2/h2_stream.c +++ b/modules/http2/h2_stream.c @@ -513,6 +513,9 @@ static apr_status_t fill_buffer(h2_stream *stream, apr_size_t amount) } status = h2_beam_receive(stream->output, stream->buffer, APR_NONBLOCK_READ, amount); + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, stream->session->c, + "h2_stream(%ld-%d): beam_received", + stream->session->id, stream->id); /* The buckets we reveive are using the stream->buffer pool as * lifetime which is exactly what we want since this is stream->pool. * diff --git a/modules/http2/h2_task.c b/modules/http2/h2_task.c index 285607220c..c22471d27f 100644 --- a/modules/http2/h2_task.c +++ b/modules/http2/h2_task.c @@ -383,6 +383,11 @@ static apr_status_t send_out(h2_task *task, apr_bucket_brigade* bb) h2_task_logio_add_bytes_out(task->c, written); } } + else { + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, task->c, + "h2_task(%s): send_out (%ld bytes)", + task->id, (long)written); + } return status; } @@ -542,8 +547,14 @@ static apr_status_t h2_filter_stream_output(ap_filter_t* filter, apr_bucket_brigade* brigade) { h2_task *task = h2_ctx_cget_task(filter->c); - AP_DEBUG_ASSERT(task); - return output_write(task, filter, brigade); + apr_status_t status; + + ap_assert(task); + status = output_write(task, filter, brigade); + if (status != APR_SUCCESS) { + h2_task_rst(task, H2_ERR_INTERNAL_ERROR); + } + return status; } static apr_status_t h2_filter_read_response(ap_filter_t* filter, -- 2.50.1