@@ -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,
|
@@ -0,0 +1,15 @@
+--- httpd/httpd/branches/2.4.x/server/core.c 2017/08/16 16:50:29 1805223
++++ httpd/httpd/branches/2.4.x/server/core.c 2017/09/08 13:13:11 1807754
+@@ -2266,6 +2266,12 @@
+ /* method has not been registered yet, but resource restriction
+ * is always checked before method handling, so register it.
+ */
++ if (cmd->pool == cmd->temp_pool) {
++ /* In .htaccess, we can't globally register new methods. */
++ return apr_psprintf(cmd->pool, "Could not register method '%s' "
++ "for %s from .htaccess configuration",
++ method, cmd->cmd->name);
++ }
+ methnum = ap_method_register(cmd->pool,
+ apr_pstrdup(cmd->pool, method));
+ }
|