summaryrefslogtreecommitdiffstats
path: root/modules/http2/h2_task.c
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2017-07-30 13:57:35 +0200
committerStefan Eissing <icing@apache.org>2017-07-30 13:57:35 +0200
commite8a012377cfc2642a9ae6105adeb1935dfdac09e (patch)
tree04ed0965686e3248d960018f41778219d5f20f6d /modules/http2/h2_task.c
parentFollow up to r1803396: CHANGES entry. (diff)
downloadapache2-e8a012377cfc2642a9ae6105adeb1935dfdac09e.tar.xz
apache2-e8a012377cfc2642a9ae6105adeb1935dfdac09e.zip
mod_http2: version bump, partial fix for stream response getting stuck, see https://github.com/icing/mod_h2/issues/143
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1803420 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'modules/http2/h2_task.c')
-rw-r--r--modules/http2/h2_task.c67
1 files changed, 41 insertions, 26 deletions
diff --git a/modules/http2/h2_task.c b/modules/http2/h2_task.c
index 1ef0d9a887..2ab4145586 100644
--- a/modules/http2/h2_task.c
+++ b/modules/http2/h2_task.c
@@ -129,7 +129,7 @@ static apr_status_t slave_out(h2_task *task, ap_filter_t* f,
apr_bucket_brigade* bb)
{
apr_bucket *b;
- apr_status_t status = APR_SUCCESS;
+ apr_status_t rv = APR_SUCCESS;
int flush = 0, blocking;
if (task->frozen) {
@@ -148,17 +148,16 @@ static apr_status_t slave_out(h2_task *task, ap_filter_t* f,
return APR_SUCCESS;
}
+send:
/* we send block once we opened the output, so someone is there
* reading it *and* the task is not assigned to a h2_req_engine */
blocking = (!task->assigned && task->output.opened);
- if (!task->output.opened) {
- for (b = APR_BRIGADE_FIRST(bb);
- b != APR_BRIGADE_SENTINEL(bb);
- b = APR_BUCKET_NEXT(b)) {
- if (APR_BUCKET_IS_FLUSH(b)) {
- flush = 1;
- break;
- }
+ for (b = APR_BRIGADE_FIRST(bb);
+ b != APR_BRIGADE_SENTINEL(bb);
+ b = APR_BUCKET_NEXT(b)) {
+ if (APR_BUCKET_IS_FLUSH(b) || APR_BUCKET_IS_EOS(b) || AP_BUCKET_IS_EOR(b)) {
+ flush = 1;
+ break;
}
}
@@ -166,32 +165,48 @@ static apr_status_t slave_out(h2_task *task, ap_filter_t* f,
/* still have data buffered from previous attempt.
* setaside and append new data and try to pass the complete data */
if (!APR_BRIGADE_EMPTY(bb)) {
- status = ap_save_brigade(f, &task->output.bb, &bb, task->pool);
+ if (APR_SUCCESS != (rv = ap_save_brigade(f, &task->output.bb, &bb, task->pool))) {
+ goto out;
+ }
}
- if (status == APR_SUCCESS) {
- status = send_out(task, task->output.bb, blocking);
- }
+ rv = send_out(task, task->output.bb, blocking);
}
else {
- /* no data buffered here, try to pass the brigade directly */
- status = send_out(task, bb, blocking);
- if (status == APR_SUCCESS && !APR_BRIGADE_EMPTY(bb)) {
- /* could not write all, buffer the rest */
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, task->c, APLOGNO(03405)
- "h2_slave_out(%s): saving brigade",
- task->id);
- status = ap_save_brigade(f, &task->output.bb, &bb, task->pool);
- flush = 1;
+ /* no data buffered previously, pass brigade directly */
+ rv = send_out(task, bb, blocking);
+
+ if (APR_SUCCESS == rv && !APR_BRIGADE_EMPTY(bb)) {
+ /* output refused to buffer it all, time to open? */
+ if (!task->output.opened && APR_SUCCESS == (rv = open_output(task))) {
+ /* Make another attempt to send the data. With the output open,
+ * the call might be blocking and send all data, so we do not need
+ * to save the brigade */
+ goto send;
+ }
+ else if (blocking && flush) {
+ /* Need to keep on doing this. */
+ goto send;
+ }
+
+ if (APR_SUCCESS == rv) {
+ /* could not write all, buffer the rest */
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, task->c, APLOGNO(03405)
+ "h2_slave_out(%s): saving brigade", task->id);
+ ap_assert(NULL);
+ rv = ap_save_brigade(f, &task->output.bb, &bb, task->pool);
+ flush = 1;
+ }
}
}
- if (status == APR_SUCCESS && !task->output.opened && flush) {
+ if (APR_SUCCESS == rv && !task->output.opened && flush) {
/* got a flush or could not write all, time to tell someone to read */
- status = open_output(task);
+ rv = open_output(task);
}
- ap_log_cerror(APLOG_MARK, APLOG_TRACE2, status, task->c,
+out:
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, rv, task->c,
"h2_slave_out(%s): slave_out leave", task->id);
- return status;
+ return rv;
}
static apr_status_t output_finish(h2_task *task)