This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "IPFire 2.x development tree".
The branch, next has been updated
via b9863c8845e12d86ffbb9a0ea0172e8b0f110d50 (commit)
from ab2eb13784502983254c70bfb915e3b9fd945bca (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit b9863c8845e12d86ffbb9a0ea0172e8b0f110d50
Author: Michael Tremer <michael.tremer(a)ipfire.org>
Date: Thu Sep 7 12:27:43 2017 +0100
apache2: Import patch for PR61382
We usually do not download patches, but rather ship them with
our source.
Signed-off-by: Michael Tremer <michael.tremer(a)ipfire.org>
-----------------------------------------------------------------------
Summary of changes:
lfs/apache2 | 7 +-
src/patches/apache-2.4.27-PR61382-fix.patch | 783 ++++++++++++++++++++++++++++
2 files changed, 785 insertions(+), 5 deletions(-)
create mode 100644 src/patches/apache-2.4.27-PR61382-fix.patch
Difference in files:
diff --git a/lfs/apache2 b/lfs/apache2
index 72a9dfa..e434d1b 100644
--- a/lfs/apache2
+++ b/lfs/apache2
@@ -41,14 +41,11 @@ DEPS = "aprutil pcre"
# Top-level Rules
###############################################################################
-objects = $(DL_FILE) \
- PR61382-Fix.patch
+objects = $(DL_FILE)
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
-PR61382-Fix.patch = ${DL_FROM}/patches/apply_to_2.4.27/PR61382-Fix.patch
$(DL_FILE)_MD5 = 97b6bbfa83c866dbe20ef317e3afd108
-PR61382-Fix.patch_MD5 = 5c1107bb1f399419574d983ce103c99a
install : $(TARGET)
@@ -78,7 +75,7 @@ $(subst %,%_MD5,$(objects)) :
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
@$(PREBUILD)
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar jxf $(DIR_DL)/$(DL_FILE)
- cd $(DIR_APP) && patch -Np0 -i $(DIR_DL)/PR61382-Fix.patch
+ cd $(DIR_APP) && patch -Np0 -i $(DIR_SRC)/src/patches/apache-2.4.27-PR61382-fix.patch
### Add IPFire's layout, too
echo "# IPFire layout" >> $(DIR_APP)/config.layout
diff --git a/src/patches/apache-2.4.27-PR61382-fix.patch b/src/patches/apache-2.4.27-PR61382-fix.patch
new file mode 100644
index 0000000..128621a
--- /dev/null
+++ b/src/patches/apache-2.4.27-PR61382-fix.patch
@@ -0,0 +1,783 @@
+Index: modules/http2/h2_bucket_beam.c
+===================================================================
+--- modules/http2/h2_bucket_beam.c (revision 1804645)
++++ modules/http2/h2_bucket_beam.c (working copy)
+@@ -287,7 +287,7 @@
+ /* do not count */
+ }
+ else if (APR_BUCKET_IS_FILE(b)) {
+- /* if unread, has no real mem footprint. how to test? */
++ /* if unread, has no real mem footprint. */
+ }
+ else {
+ len += b->length;
+@@ -316,32 +316,80 @@
+ return APR_SIZE_MAX;
+ }
+
+-static apr_status_t wait_cond(h2_bucket_beam *beam, apr_thread_mutex_t *lock)
++static int buffer_is_empty(h2_bucket_beam *beam)
+ {
+- if (beam->timeout > 0) {
+- return apr_thread_cond_timedwait(beam->cond, lock, beam->timeout);
++ return ((!beam->recv_buffer || APR_BRIGADE_EMPTY(beam->recv_buffer))
++ && H2_BLIST_EMPTY(&beam->send_list));
++}
++
++static apr_status_t wait_empty(h2_bucket_beam *beam, apr_read_type_e block,
++ apr_thread_mutex_t *lock)
++{
++ apr_status_t rv = APR_SUCCESS;
++
++ while (!buffer_is_empty(beam) && APR_SUCCESS == rv) {
++ if (APR_BLOCK_READ != block || !lock) {
++ rv = APR_EAGAIN;
++ }
++ else if (beam->timeout > 0) {
++ rv = apr_thread_cond_timedwait(beam->change, lock, beam->timeout);
++ }
++ else {
++ rv = apr_thread_cond_wait(beam->change, lock);
++ }
+ }
+- else {
+- return apr_thread_cond_wait(beam->cond, lock);
++ return rv;
++}
++
++static apr_status_t wait_not_empty(h2_bucket_beam *beam, apr_read_type_e block,
++ apr_thread_mutex_t *lock)
++{
++ apr_status_t rv = APR_SUCCESS;
++
++ while (buffer_is_empty(beam) && APR_SUCCESS == rv) {
++ if (beam->aborted) {
++ rv = APR_ECONNABORTED;
++ }
++ else if (beam->closed) {
++ rv = APR_EOF;
++ }
++ else if (APR_BLOCK_READ != block || !lock) {
++ rv = APR_EAGAIN;
++ }
++ else if (beam->timeout > 0) {
++ rv = apr_thread_cond_timedwait(beam->change, lock, beam->timeout);
++ }
++ else {
++ rv = apr_thread_cond_wait(beam->change, lock);
++ }
+ }
++ return rv;
+ }
+
+-static apr_status_t r_wait_space(h2_bucket_beam *beam, apr_read_type_e block,
+- h2_beam_lock *pbl, apr_size_t *premain)
++static apr_status_t wait_not_full(h2_bucket_beam *beam, apr_read_type_e block,
++ apr_size_t *pspace_left, h2_beam_lock *bl)
+ {
+- *premain = calc_space_left(beam);
+- while (!beam->aborted && *premain <= 0
+- && (block == APR_BLOCK_READ) && pbl->mutex) {
+- apr_status_t status;
+- report_prod_io(beam, 1, pbl);
+- status = wait_cond(beam, pbl->mutex);
+- if (APR_STATUS_IS_TIMEUP(status)) {
+- return status;
++ apr_status_t rv = APR_SUCCESS;
++ apr_size_t left;
++
++ while (0 == (left = calc_space_left(beam)) && APR_SUCCESS == rv) {
++ if (beam->aborted) {
++ rv = APR_ECONNABORTED;
+ }
+- r_purge_sent(beam);
+- *premain = calc_space_left(beam);
++ else if (block != APR_BLOCK_READ || !bl->mutex) {
++ rv = APR_EAGAIN;
++ }
++ else {
++ if (beam->timeout > 0) {
++ rv = apr_thread_cond_timedwait(beam->change, bl->mutex, beam->timeout);
++ }
++ else {
++ rv = apr_thread_cond_wait(beam->change, bl->mutex);
++ }
++ }
+ }
+- return beam->aborted? APR_ECONNABORTED : APR_SUCCESS;
++ *pspace_left = left;
++ return rv;
+ }
+
+ static void h2_beam_emitted(h2_bucket_beam *beam, h2_beam_proxy *proxy)
+@@ -404,8 +452,8 @@
+ if (!bl.mutex) {
+ r_purge_sent(beam);
+ }
+- else if (beam->cond) {
+- apr_thread_cond_broadcast(beam->cond);
++ else {
++ apr_thread_cond_broadcast(beam->change);
+ }
+ leave_yellow(beam, &bl);
+ }
+@@ -425,9 +473,7 @@
+ {
+ if (!beam->closed) {
+ beam->closed = 1;
+- if (beam->cond) {
+- apr_thread_cond_broadcast(beam->cond);
+- }
++ apr_thread_cond_broadcast(beam->change);
+ }
+ return APR_SUCCESS;
+ }
+@@ -582,7 +628,7 @@
+ apr_interval_time_t timeout)
+ {
+ h2_bucket_beam *beam;
+- apr_status_t status = APR_SUCCESS;
++ apr_status_t rv = APR_SUCCESS;
+
+ beam = apr_pcalloc(pool, sizeof(*beam));
+ if (!beam) {
+@@ -601,16 +647,15 @@
+ beam->max_buf_size = max_buf_size;
+ beam->timeout = timeout;
+
+- status = apr_thread_mutex_create(&beam->lock, APR_THREAD_MUTEX_DEFAULT,
+- pool);
+- if (status == APR_SUCCESS) {
+- status = apr_thread_cond_create(&beam->cond, pool);
+- if (status == APR_SUCCESS) {
++ rv = apr_thread_mutex_create(&beam->lock, APR_THREAD_MUTEX_DEFAULT, pool);
++ if (APR_SUCCESS == rv) {
++ rv = apr_thread_cond_create(&beam->change, pool);
++ if (APR_SUCCESS == rv) {
+ apr_pool_pre_cleanup_register(pool, beam, beam_cleanup);
+ *pbeam = beam;
+ }
+ }
+- return status;
++ return rv;
+ }
+
+ void h2_beam_buffer_size_set(h2_bucket_beam *beam, apr_size_t buffer_size)
+@@ -691,9 +736,7 @@
+ h2_blist_cleanup(&beam->send_list);
+ report_consumption(beam, &bl);
+ }
+- if (beam->cond) {
+- apr_thread_cond_broadcast(beam->cond);
+- }
++ apr_thread_cond_broadcast(beam->change);
+ leave_yellow(beam, &bl);
+ }
+ }
+@@ -730,18 +773,7 @@
+ h2_beam_lock bl;
+
+ if ((status = enter_yellow(beam, &bl)) == APR_SUCCESS) {
+- while (status == APR_SUCCESS
+- && !H2_BLIST_EMPTY(&beam->send_list)
+- && !H2_BPROXY_LIST_EMPTY(&beam->proxies)) {
+- if (block == APR_NONBLOCK_READ || !bl.mutex) {
+- status = APR_EAGAIN;
+- break;
+- }
+- if (beam->cond) {
+- apr_thread_cond_broadcast(beam->cond);
+- }
+- status = wait_cond(beam, bl.mutex);
+- }
++ status = wait_empty(beam, block, bl.mutex);
+ leave_yellow(beam, &bl);
+ }
+ return status;
+@@ -761,13 +793,18 @@
+ static apr_status_t append_bucket(h2_bucket_beam *beam,
+ apr_bucket *b,
+ apr_read_type_e block,
++ apr_size_t *pspace_left,
+ h2_beam_lock *pbl)
+ {
+ const char *data;
+ apr_size_t len;
+- apr_size_t space_left = 0;
+ apr_status_t status;
++ int can_beam, check_len;
+
++ if (beam->aborted) {
++ return APR_ECONNABORTED;
++ }
++
+ if (APR_BUCKET_IS_METADATA(b)) {
+ if (APR_BUCKET_IS_EOS(b)) {
+ beam->closed = 1;
+@@ -777,11 +814,31 @@
+ return APR_SUCCESS;
+ }
+ else if (APR_BUCKET_IS_FILE(b)) {
+- /* file bucket lengths do not really count */
++ /* For file buckets the problem is their internal readpool that
++ * is used on the first read to allocate buffer/mmap.
++ * Since setting aside a file bucket will de-register the
++ * file cleanup function from the previous pool, we need to
++ * call that only from the sender thread.
++ *
++ * Currently, we do not handle file bucket with refcount > 1 as
++ * the beam is then not in complete control of the file's lifetime.
++ * Which results in the bug that a file get closed by the receiver
++ * while the sender or the beam still have buckets using it.
++ *
++ * Additionally, we allow callbacks to prevent beaming file
++ * handles across. The use case for this is to limit the number
++ * of open file handles and rather use a less efficient beam
++ * transport. */
++ apr_bucket_file *bf = b->data;
++ apr_file_t *fd = bf->fd;
++ can_beam = (bf->refcount.refcount == 1);
++ if (can_beam && beam->can_beam_fn) {
++ can_beam = beam->can_beam_fn(beam->can_beam_ctx, beam, fd);
++ }
++ check_len = !can_beam;
+ }
+ else {
+- space_left = calc_space_left(beam);
+- if (space_left > 0 && b->length == ((apr_size_t)-1)) {
++ if (b->length == ((apr_size_t)-1)) {
+ const char *data;
+ status = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
+ if (status != APR_SUCCESS) {
+@@ -788,19 +845,15 @@
+ return status;
+ }
+ }
+-
+- if (space_left <= 0) {
+- status = r_wait_space(beam, block, pbl, &space_left);
+- if (status != APR_SUCCESS) {
+- return status;
+- }
+- if (space_left <= 0) {
+- return APR_EAGAIN;
+- }
++ check_len = 1;
++ }
++
++ if (check_len) {
++ if (b->length > *pspace_left) {
++ apr_bucket_split(b, *pspace_left);
+ }
+- /* space available, maybe need bucket split */
++ *pspace_left -= b->length;
+ }
+-
+
+ /* The fundamental problem is that reading a sender bucket from
+ * a receiver thread is a total NO GO, because the bucket might use
+@@ -830,32 +883,8 @@
+ apr_bucket_heap_make(b, data, len, NULL);
+ }
+ }
+- else if (APR_BUCKET_IS_FILE(b)) {
+- /* For file buckets the problem is their internal readpool that
+- * is used on the first read to allocate buffer/mmap.
+- * Since setting aside a file bucket will de-register the
+- * file cleanup function from the previous pool, we need to
+- * call that only from the sender thread.
+- *
+- * Currently, we do not handle file bucket with refcount > 1 as
+- * the beam is then not in complete control of the file's lifetime.
+- * Which results in the bug that a file get closed by the receiver
+- * while the sender or the beam still have buckets using it.
+- *
+- * Additionally, we allow callbacks to prevent beaming file
+- * handles across. The use case for this is to limit the number
+- * of open file handles and rather use a less efficient beam
+- * transport. */
+- apr_bucket_file *bf = b->data;
+- apr_file_t *fd = bf->fd;
+- int can_beam = (bf->refcount.refcount == 1);
+- if (can_beam && beam->can_beam_fn) {
+- can_beam = beam->can_beam_fn(beam->can_beam_ctx, beam, fd);
+- }
+- if (can_beam) {
+- status = apr_bucket_setaside(b, beam->send_pool);
+- }
+- /* else: enter ENOTIMPL case below */
++ else if (APR_BUCKET_IS_FILE(b) && can_beam) {
++ status = apr_bucket_setaside(b, beam->send_pool);
+ }
+
+ if (status == APR_ENOTIMPL) {
+@@ -865,12 +894,6 @@
+ * a counter example).
+ * We do the read while in the sender thread, so that the bucket may
+ * use pools/allocators safely. */
+- if (space_left < APR_BUCKET_BUFF_SIZE) {
+- space_left = APR_BUCKET_BUFF_SIZE;
+- }
+- if (space_left < b->length) {
+- apr_bucket_split(b, space_left);
+- }
+ status = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
+ if (status == APR_SUCCESS) {
+ status = apr_bucket_setaside(b, beam->send_pool);
+@@ -884,7 +907,7 @@
+ APR_BUCKET_REMOVE(b);
+ H2_BLIST_INSERT_TAIL(&beam->send_list, b);
+ beam->sent_bytes += b->length;
+-
++
+ return APR_SUCCESS;
+ }
+
+@@ -904,7 +927,8 @@
+ apr_read_type_e block)
+ {
+ apr_bucket *b;
+- apr_status_t status = APR_SUCCESS;
++ apr_status_t rv = APR_SUCCESS;
++ apr_size_t space_left = 0;
+ h2_beam_lock bl;
+
+ /* Called from the sender thread to add buckets to the beam */
+@@ -914,23 +938,31 @@
+
+ if (beam->aborted) {
+ move_to_hold(beam, sender_bb);
+- status = APR_ECONNABORTED;
++ rv = APR_ECONNABORTED;
+ }
+ else if (sender_bb) {
+- int force_report = !APR_BRIGADE_EMPTY(sender_bb);
+- while (!APR_BRIGADE_EMPTY(sender_bb) && status == APR_SUCCESS) {
++ int force_report = !APR_BRIGADE_EMPTY(sender_bb);
++
++ space_left = calc_space_left(beam);
++ while (!APR_BRIGADE_EMPTY(sender_bb) && APR_SUCCESS == rv) {
++ if (space_left <= 0) {
++ report_prod_io(beam, force_report, &bl);
++ rv = wait_not_full(beam, block, &space_left, &bl);
++ if (APR_SUCCESS != rv) {
++ break;
++ }
++ }
+ b = APR_BRIGADE_FIRST(sender_bb);
+- status = append_bucket(beam, b, block, &bl);
++ rv = append_bucket(beam, b, block, &space_left, &bl);
+ }
++
+ report_prod_io(beam, force_report, &bl);
+- if (beam->cond) {
+- apr_thread_cond_broadcast(beam->cond);
+- }
++ apr_thread_cond_broadcast(beam->change);
+ }
+ report_consumption(beam, &bl);
+ leave_yellow(beam, &bl);
+ }
+- return status;
++ return rv;
+ }
+
+ apr_status_t h2_beam_receive(h2_bucket_beam *beam,
+@@ -942,11 +974,16 @@
+ apr_bucket *bsender, *brecv, *ng;
+ int transferred = 0;
+ apr_status_t status = APR_SUCCESS;
+- apr_off_t remain = readbytes;
++ apr_off_t remain;
+ int transferred_buckets = 0;
+
+ /* Called from the receiver thread to take buckets from the beam */
+ if (enter_yellow(beam, &bl) == APR_SUCCESS) {
++ if (readbytes <= 0) {
++ readbytes = APR_SIZE_MAX;
++ }
++ remain = readbytes;
++
+ transfer:
+ if (beam->aborted) {
+ recv_buffer_cleanup(beam, &bl);
+@@ -955,11 +992,12 @@
+ }
+
+ /* transfer enough buckets from our receiver brigade, if we have one */
+- while (beam->recv_buffer
+- && !APR_BRIGADE_EMPTY(beam->recv_buffer)
+- && (readbytes <= 0 || remain >= 0)) {
++ while (remain >= 0
++ && beam->recv_buffer
++ && !APR_BRIGADE_EMPTY(beam->recv_buffer)) {
++
+ brecv = APR_BRIGADE_FIRST(beam->recv_buffer);
+- if (readbytes > 0 && brecv->length > 0 && remain <= 0) {
++ if (brecv->length > 0 && remain <= 0) {
+ break;
+ }
+ APR_BUCKET_REMOVE(brecv);
+@@ -970,11 +1008,11 @@
+
+ /* transfer from our sender brigade, transforming sender buckets to
+ * receiver ones until we have enough */
+- while (!H2_BLIST_EMPTY(&beam->send_list) && (readbytes <= 0 || remain >= 0)) {
+- bsender = H2_BLIST_FIRST(&beam->send_list);
++ while (remain >= 0 && !H2_BLIST_EMPTY(&beam->send_list)) {
++
+ brecv = NULL;
+-
+- if (readbytes > 0 && bsender->length > 0 && remain <= 0) {
++ bsender = H2_BLIST_FIRST(&beam->send_list);
++ if (bsender->length > 0 && remain <= 0) {
+ break;
+ }
+
+@@ -1020,11 +1058,12 @@
+ * been handed out. See also PR 59348 */
+ apr_bucket_file_enable_mmap(ng, 0);
+ #endif
+- remain -= bsender->length;
+- ++transferred;
+ APR_BUCKET_REMOVE(bsender);
+ H2_BLIST_INSERT_TAIL(&beam->hold_list, bsender);
++
++ remain -= bsender->length;
+ ++transferred;
++ ++transferred_buckets;
+ continue;
+ }
+ else {
+@@ -1041,6 +1080,7 @@
+ * receiver bucket references it any more. */
+ APR_BUCKET_REMOVE(bsender);
+ H2_BLIST_INSERT_TAIL(&beam->hold_list, bsender);
++
+ beam->received_bytes += bsender->length;
+ ++transferred_buckets;
+
+@@ -1063,8 +1103,8 @@
+ }
+ }
+
+- if (readbytes > 0 && remain < 0) {
+- /* too much, put some back */
++ if (remain < 0) {
++ /* too much, put some back into out recv_buffer */
+ remain = readbytes;
+ for (brecv = APR_BRIGADE_FIRST(bb);
+ brecv != APR_BRIGADE_SENTINEL(bb);
+@@ -1081,15 +1121,7 @@
+ }
+ }
+
+- if (transferred_buckets > 0) {
+- if (beam->cons_ev_cb) {
+- beam->cons_ev_cb(beam->cons_ctx, beam);
+- }
+- }
+-
+- if (beam->closed
+- && (!beam->recv_buffer || APR_BRIGADE_EMPTY(beam->recv_buffer))
+- && H2_BLIST_EMPTY(&beam->send_list)) {
++ if (beam->closed && buffer_is_empty(beam)) {
+ /* beam is closed and we have nothing more to receive */
+ if (!beam->close_sent) {
+ apr_bucket *b = apr_bucket_eos_create(bb->bucket_alloc);
+@@ -1100,28 +1132,23 @@
+ }
+ }
+
++ if (transferred_buckets > 0) {
++ if (beam->cons_ev_cb) {
++ beam->cons_ev_cb(beam->cons_ctx, beam);
++ }
++ }
++
+ if (transferred) {
+- if (beam->cond) {
+- apr_thread_cond_broadcast(beam->cond);
+- }
++ apr_thread_cond_broadcast(beam->change);
+ status = APR_SUCCESS;
+ }
+- else if (beam->closed) {
+- status = APR_EOF;
+- }
+- else if (block == APR_BLOCK_READ && bl.mutex && beam->cond) {
+- status = wait_cond(beam, bl.mutex);
++ else {
++ status = wait_not_empty(beam, block, bl.mutex);
+ if (status != APR_SUCCESS) {
+ goto leave;
+ }
+ goto transfer;
+ }
+- else {
+- if (beam->cond) {
+- apr_thread_cond_broadcast(beam->cond);
+- }
+- status = APR_EAGAIN;
+- }
+ leave:
+ leave_yellow(beam, &bl);
+ }
+Index: modules/http2/h2_bucket_beam.h
+===================================================================
+--- modules/http2/h2_bucket_beam.h (revision 1804645)
++++ modules/http2/h2_bucket_beam.h (working copy)
+@@ -190,7 +190,7 @@
+ unsigned int tx_mem_limits : 1; /* only memory size counts on transfers */
+
+ struct apr_thread_mutex_t *lock;
+- struct apr_thread_cond_t *cond;
++ struct apr_thread_cond_t *change;
+ void *m_ctx;
+ h2_beam_mutex_enter *m_enter;
+
+Index: modules/http2/h2_stream.c
+===================================================================
+--- modules/http2/h2_stream.c (revision 1804645)
++++ modules/http2/h2_stream.c (working copy)
+@@ -774,20 +774,20 @@
+ return NULL;
+ }
+
+-static apr_status_t add_data(h2_stream *stream, apr_off_t requested,
+- apr_off_t *plen, int *peos, int *complete,
+- h2_headers **pheaders)
++static apr_status_t add_buffered_data(h2_stream *stream, apr_off_t requested,
++ apr_off_t *plen, int *peos, int *is_all,
++ h2_headers **pheaders)
+ {
+ apr_bucket *b, *e;
+
+ *peos = 0;
+ *plen = 0;
+- *complete = 0;
++ *is_all = 0;
+ if (pheaders) {
+ *pheaders = NULL;
+ }
+
+- H2_STREAM_OUT_LOG(APLOG_TRACE2, stream, "add_data");
++ H2_STREAM_OUT_LOG(APLOG_TRACE2, stream, "add_buffered_data");
+ b = APR_BRIGADE_FIRST(stream->out_buffer);
+ while (b != APR_BRIGADE_SENTINEL(stream->out_buffer)) {
+ e = APR_BUCKET_NEXT(b);
+@@ -833,7 +833,7 @@
+ }
+ b = e;
+ }
+- *complete = 1;
++ *is_all = 1;
+ return APR_SUCCESS;
+ }
+
+@@ -865,7 +865,7 @@
+ requested = (*plen > 0)? H2MIN(*plen, max_chunk) : max_chunk;
+
+ /* count the buffered data until eos or a headers bucket */
+- status = add_data(stream, requested, plen, peos, &complete, pheaders);
++ status = add_buffered_data(stream, requested, plen, peos, &complete, pheaders);
+
+ if (status == APR_EAGAIN) {
+ /* TODO: ugly, someone needs to retrieve the response first */
+@@ -882,29 +882,39 @@
+ return APR_SUCCESS;
+ }
+
++ /* If there we do not have enough buffered data to satisfy the requested
++ * length *and* we counted the _complete_ buffer (and did not stop in the middle
++ * because of meta data there), lets see if we can read more from the
++ * output beam */
+ missing = H2MIN(requested, stream->max_mem) - *plen;
+ if (complete && !*peos && missing > 0) {
++ apr_status_t rv = APR_EOF;
++
+ if (stream->output) {
+ H2_STREAM_OUT_LOG(APLOG_TRACE2, stream, "pre");
+- status = h2_beam_receive(stream->output, stream->out_buffer,
+- APR_NONBLOCK_READ,
+- stream->max_mem - *plen);
++ rv = h2_beam_receive(stream->output, stream->out_buffer,
++ APR_NONBLOCK_READ, stream->max_mem - *plen);
+ H2_STREAM_OUT_LOG(APLOG_TRACE2, stream, "post");
+ }
+- else {
+- status = APR_EOF;
++
++ if (rv == APR_SUCCESS) {
++ /* count the buffer again, now that we have read output */
++ status = add_buffered_data(stream, requested, plen, peos, &complete, pheaders);
+ }
+-
+- if (APR_STATUS_IS_EOF(status)) {
++ else if (APR_STATUS_IS_EOF(rv)) {
+ apr_bucket *eos = apr_bucket_eos_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(stream->out_buffer, eos);
+ *peos = 1;
+- status = APR_SUCCESS;
+ }
+- else if (status == APR_SUCCESS) {
+- /* do it again, now that we have gotten more */
+- status = add_data(stream, requested, plen, peos, &complete, pheaders);
++ else if (APR_STATUS_IS_EAGAIN(rv)) {
++ /* we set this is the status of this call only if there
++ * is no buffered data, see check below */
+ }
++ else {
++ /* real error reading. Give this back directly, even though
++ * we may have something buffered. */
++ status = rv;
++ }
+ }
+
+ if (status == APR_SUCCESS) {
+Index: modules/http2/h2_task.c
+===================================================================
+--- modules/http2/h2_task.c (revision 1804645)
++++ modules/http2/h2_task.c (working copy)
+@@ -129,7 +129,7 @@
+ 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 @@
+ 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 @@
+ /* 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)
+Index: modules/http2/h2_version.h
+===================================================================
+--- modules/http2/h2_version.h (revision 1804645)
++++ modules/http2/h2_version.h (working copy)
+@@ -26,7 +26,7 @@
+ * @macro
+ * Version number of the http2 module as c string
+ */
+-#define MOD_HTTP2_VERSION "1.10.7"
++#define MOD_HTTP2_VERSION "1.10.10"
+
+ /**
+ * @macro
+@@ -34,7 +34,7 @@
+ * release. This is a 24 bit number with 8 bits for major number, 8 bits
+ * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
+ */
+-#define MOD_HTTP2_VERSION_NUM 0x010a06
++#define MOD_HTTP2_VERSION_NUM 0x010a0a
+
+
+ #endif /* mod_h2_h2_version_h */
+Index: modules/http2
+===================================================================
+--- modules/http2 (revision 1804645)
++++ modules/http2 (working copy)
+
+Property changes on: modules/http2
+___________________________________________________________________
+Modified: svn:mergeinfo
+## -0,0 +0,1 ##
+ Merged /httpd/httpd/trunk/modules/http2:r1803420,1803454,1804090
+Index: .
+===================================================================
+--- . (revision 1804645)
++++ . (working copy)
+
+Property changes on: .
+___________________________________________________________________
+Modified: svn:mergeinfo
+## -0,0 +0,1 ##
+ Merged /httpd/httpd/trunk:r1803420,1803454,1804090
hooks/post-receive
--
IPFire 2.x development tree