You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by mi...@apache.org on 2021/09/26 14:30:52 UTC

svn commit: r1893658 - in /httpd/httpd/branches/2.4.x: ./ modules/http2/

Author: minfrin
Date: Sun Sep 26 14:30:51 2021
New Revision: 1893658

URL: http://svn.apache.org/viewvc?rev=1893658&view=rev
Log:
Backport:

*) mod_http2: when a server is restarted gracefully, any idle h2 worker
   threads are shut down immediately.
   Also, change OpenSSL API use for deprecations in OpenSSL 3.0.
   Adds all other, never proposed code changes to make a clean
   sync of http2 sources.
   trunk patch: http://svn.apache.org/r1893214
                http://svn.apache.org/r1893215
                http://svn.apache.org/r1893220
                and other never proposed code changes
   PR: https://github.com/apache/httpd/pull/270
   +1: icing, rpluem, minfrin


Modified:
    httpd/httpd/branches/2.4.x/CHANGES
    httpd/httpd/branches/2.4.x/STATUS
    httpd/httpd/branches/2.4.x/modules/http2/h2_alt_svc.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_beam.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_config.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_conn.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_conn.h
    httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_headers.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_headers.h
    httpd/httpd/branches/2.4.x/modules/http2/h2_mplx.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_push.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_push.h
    httpd/httpd/branches/2.4.x/modules/http2/h2_request.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_session.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_session.h
    httpd/httpd/branches/2.4.x/modules/http2/h2_task.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_task.h
    httpd/httpd/branches/2.4.x/modules/http2/h2_util.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_version.h
    httpd/httpd/branches/2.4.x/modules/http2/h2_workers.c
    httpd/httpd/branches/2.4.x/modules/http2/h2_workers.h
    httpd/httpd/branches/2.4.x/modules/http2/mod_http2.c
    httpd/httpd/branches/2.4.x/modules/http2/mod_proxy_http2.c

Modified: httpd/httpd/branches/2.4.x/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/CHANGES?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/2.4.x/CHANGES [utf-8] Sun Sep 26 14:30:51 2021
@@ -1,6 +1,12 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.4.50
 
+  *) mod_http2: when a server is restarted gracefully, any idle h2 worker
+     threads are shut down immediately.
+     Also, change OpenSSL API use for deprecations in OpenSSL 3.0.
+     Adds all other, never proposed code changes to make a clean
+     sync of http2 sources. [Stefan Eissing]
+
   *) mod_dav: Correctly handle errors returned by dav providers on REPORT
      requests. [Ruediger Pluem]
 

Modified: httpd/httpd/branches/2.4.x/STATUS
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/STATUS?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/STATUS (original)
+++ httpd/httpd/branches/2.4.x/STATUS Sun Sep 26 14:30:51 2021
@@ -142,18 +142,6 @@ RELEASE SHOWSTOPPERS:
 PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
-  *) mod_http2: when a server is restarted gracefully, any idle h2 worker
-     threads are shut down immediately.
-     Also, change OpenSSL API use for deprecations in OpenSLL 3.0.
-     Adds all other, never proposed code changes to make a clean
-     sync of http2 sources.
-     trunk patch: http://svn.apache.org/r1893214
-                  http://svn.apache.org/r1893215
-                  http://svn.apache.org/r1893220
-                  and other never proposed code changes
-     PR: https://github.com/apache/httpd/pull/270
-     +1: icing, rpluem, minfrin
-
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
   [ New proposals should be added at the end of the list ]

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_alt_svc.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_alt_svc.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_alt_svc.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_alt_svc.c Sun Sep 26 14:30:51 2021
@@ -47,14 +47,14 @@ h2_alt_svc *h2_alt_svc_parse(const char
 {
     const char *sep = ap_strchr_c(s, '=');
     if (sep) {
-        const char *alpn = apr_pstrmemdup(pool, s, sep - s);
+        const char *alpn = apr_pstrmemdup(pool, s, (apr_size_t)(sep - s));
         const char *host = NULL;
         int port = 0;
         s = sep + 1;
         sep = ap_strchr_c(s, ':');  /* mandatory : */
         if (sep) {
             if (sep != s) {    /* optional host */
-                host = apr_pstrmemdup(pool, s, sep - s);
+                host = apr_pstrmemdup(pool, s, (apr_size_t)(sep - s));
             }
             s = sep + 1;
             if (*s) {          /* must be a port number */

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_beam.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_beam.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_beam.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_beam.c Sun Sep 26 14:30:51 2021
@@ -216,6 +216,7 @@ static apr_status_t enter_yellow(h2_buck
 
 static void leave_yellow(h2_bucket_beam *beam, h2_beam_lock *pbl)
 {
+    (void)beam;
     if (pbl->leave) {
         pbl->leave(pbl->mutex);
     }
@@ -228,7 +229,7 @@ static apr_off_t bucket_mem_used(apr_buc
     }
     else {
         /* should all have determinate length */
-        return b->length;
+        return (apr_off_t)b->length;
     }
 }
 
@@ -302,7 +303,7 @@ static void r_purge_sent(h2_bucket_beam
 static apr_size_t calc_space_left(h2_bucket_beam *beam)
 {
     if (beam->max_buf_size > 0) {
-        apr_off_t len = calc_buffered(beam);
+        apr_size_t len = calc_buffered(beam);
         return (beam->max_buf_size > len? (beam->max_buf_size - len) : 0);
     }
     return APR_SIZE_MAX;
@@ -777,6 +778,8 @@ static apr_status_t append_bucket(h2_buc
     apr_status_t status;
     int can_beam = 0, check_len;
     
+    (void)block;
+    (void)pbl;
     if (beam->aborted) {
         return APR_ECONNABORTED;
     }
@@ -815,8 +818,8 @@ static apr_status_t append_bucket(h2_buc
     }
     else {
         if (b->length == ((apr_size_t)-1)) {
-            const char *data;
-            status = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
+            const char *data2;
+            status = apr_bucket_read(b, &data2, &len, APR_BLOCK_READ);
             if (status != APR_SUCCESS) {
                 return status;
             }
@@ -958,7 +961,7 @@ apr_status_t h2_beam_receive(h2_bucket_b
     /* 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;
+            readbytes = (apr_off_t)APR_SIZE_MAX;
         }
         remain = readbytes;
         
@@ -1028,7 +1031,7 @@ transfer:
                     }
                     ++beam->files_beamed;
                 }
-                ng = apr_brigade_insert_file(bb, fd, bsender->start, bsender->length, 
+                ng = apr_brigade_insert_file(bb, fd, bsender->start, (apr_off_t)bsender->length, 
                                              bb->p);
 #if APR_HAS_MMAP
                 /* disable mmap handling as this leads to segfaults when
@@ -1089,9 +1092,9 @@ transfer:
                  brecv != APR_BRIGADE_SENTINEL(bb);
                  brecv = APR_BUCKET_NEXT(brecv)) {
                 remain -= (beam->tx_mem_limits? bucket_mem_used(brecv) 
-                           : brecv->length);
+                           : (apr_off_t)brecv->length);
                 if (remain < 0) {
-                    apr_bucket_split(brecv, brecv->length+remain);
+                    apr_bucket_split(brecv, (apr_size_t)((apr_off_t)brecv->length+remain));
                     beam->recv_buffer = apr_brigade_split_ex(bb, 
                                                              APR_BUCKET_NEXT(brecv), 
                                                              beam->recv_buffer);
@@ -1258,6 +1261,7 @@ apr_size_t h2_beam_get_files_beamed(h2_b
 
 int h2_beam_no_files(void *ctx, h2_bucket_beam *beam, apr_file_t *file)
 {
+    (void)ctx; (void)beam; (void)file;
     return 0;
 }
 

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_bucket_eos.c Sun Sep 26 14:30:51 2021
@@ -13,22 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
 
 #include <assert.h>
 #include <stddef.h>

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_config.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_config.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_config.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_config.c Sun Sep 26 14:30:51 2021
@@ -542,7 +542,7 @@ const struct h2_priority *h2_cconfig_get
 {
     const h2_config *conf = h2_config_get(c);
     if (content_type && conf->priorities) {
-        size_t len = strcspn(content_type, "; \t");
+        apr_ssize_t len = (apr_ssize_t)strcspn(content_type, "; \t");
         h2_priority *prio = apr_hash_get(conf->priorities, content_type, len);
         return prio? prio : apr_hash_get(conf->priorities, "*", 1);
     }
@@ -711,7 +711,8 @@ static const char *h2_conf_add_push_prio
     h2_dependency dependency;
     h2_priority *priority;
     int weight;
-    
+ 
+    (void)_cfg;
     if (!*ctype) {
         return "1st argument must be a mime-type, like 'text/css' or '*'";
     }
@@ -730,7 +731,7 @@ static const char *h2_conf_add_push_prio
     else if (!strcasecmp("BEFORE", sdependency)) {
         dependency = H2_DEPENDANT_BEFORE;
         if (sweight) {
-            return "dependecy 'Before' does not allow a weight";
+            return "dependency 'Before' does not allow a weight";
         }
     } 
     else if (!strcasecmp("INTERLEAVED", sdependency)) {
@@ -754,7 +755,7 @@ static const char *h2_conf_add_push_prio
     if (!cfg->priorities) {
         cfg->priorities = apr_hash_make(cmd->pool);
     }
-    apr_hash_set(cfg->priorities, ctype, strlen(ctype), priority);
+    apr_hash_set(cfg->priorities, ctype, (apr_ssize_t)strlen(ctype), priority);
     return NULL;
 }
 

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_conn.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_conn.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_conn.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_conn.c Sun Sep 26 14:30:51 2021
@@ -148,6 +148,13 @@ apr_status_t h2_conn_child_init(apr_pool
     return status;
 }
 
+void h2_conn_child_stopping(apr_pool_t *pool, int graceful)
+{
+    if (workers && graceful) {
+        h2_workers_graceful_shutdown(workers);
+    }
+}
+
 h2_mpm_type_t h2_conn_mpm_type(void)
 {
     check_modules(0);
@@ -259,6 +266,8 @@ apr_status_t h2_conn_run(conn_rec *c)
 apr_status_t h2_conn_pre_close(struct h2_ctx *ctx, conn_rec *c)
 {
     h2_session *session = h2_ctx_get_session(c);
+    
+    (void)c;
     if (session) {
         apr_status_t status = h2_session_pre_close(session, async_mpm);
         return (status == APR_SUCCESS)? DONE : status;
@@ -266,6 +275,13 @@ apr_status_t h2_conn_pre_close(struct h2
     return DONE;
 }
 
+/* APR callback invoked if allocation fails. */
+static int abort_on_oom(int retcode)
+{
+    ap_abort_on_oom();
+    return retcode; /* unreachable, hopefully. */
+}
+
 conn_rec *h2_secondary_create(conn_rec *master, int sec_id, apr_pool_t *parent)
 {
     apr_allocator_t *allocator;
@@ -295,8 +311,9 @@ conn_rec *h2_secondary_create(conn_rec *
         return NULL;
     }
     apr_allocator_owner_set(allocator, pool);
+    apr_pool_abort_set(abort_on_oom, pool);
     apr_pool_tag(pool, "h2_secondary_conn");
- 
+
     c = (conn_rec *) apr_palloc(pool, sizeof(conn_rec));
     if (c == NULL) {
         ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, master, 

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_conn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_conn.h?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_conn.h (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_conn.h Sun Sep 26 14:30:51 2021
@@ -45,12 +45,17 @@ apr_status_t h2_conn_run(conn_rec *c);
  */
 apr_status_t h2_conn_pre_close(struct h2_ctx *ctx, conn_rec *c);
 
-/* Initialize this child process for h2 connection work,
+/**
+ * Initialize this child process for h2 connection work,
  * to be called once during child init before multi processing
  * starts.
  */
 apr_status_t h2_conn_child_init(apr_pool_t *pool, server_rec *s);
 
+/**
+ * Child is about to be stopped, release unused resources
+ */
+void h2_conn_child_stopping(apr_pool_t *pool, int graceful);
 
 typedef enum {
     H2_MPM_UNKNOWN,

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_conn_io.c Sun Sep 26 14:30:51 2021
@@ -54,16 +54,18 @@
  */
 #define WRITE_SIZE_MAX        (TLS_DATA_MAX) 
 
+#define BUF_REMAIN            ((apr_size_t)(bmax-off))
 
 static void h2_conn_io_bb_log(conn_rec *c, int stream_id, int level, 
                               const char *tag, apr_bucket_brigade *bb)
 {
     char buffer[16 * 1024];
     const char *line = "(null)";
-    apr_size_t bmax = sizeof(buffer)/sizeof(buffer[0]);
+    int bmax = sizeof(buffer)/sizeof(buffer[0]);
     int off = 0;
     apr_bucket *b;
     
+    (void)stream_id;
     if (bb) {
         memset(buffer, 0, bmax--);
         for (b = APR_BRIGADE_FIRST(bb); 
@@ -72,19 +74,19 @@ static void h2_conn_io_bb_log(conn_rec *
             
             if (APR_BUCKET_IS_METADATA(b)) {
                 if (APR_BUCKET_IS_EOS(b)) {
-                    off += apr_snprintf(buffer+off, bmax-off, "eos ");
+                    off += apr_snprintf(buffer+off, BUF_REMAIN, "eos ");
                 }
                 else if (APR_BUCKET_IS_FLUSH(b)) {
-                    off += apr_snprintf(buffer+off, bmax-off, "flush ");
+                    off += apr_snprintf(buffer+off, BUF_REMAIN, "flush ");
                 }
                 else if (AP_BUCKET_IS_EOR(b)) {
-                    off += apr_snprintf(buffer+off, bmax-off, "eor ");
+                    off += apr_snprintf(buffer+off, BUF_REMAIN, "eor ");
                 }
                 else if (H2_BUCKET_IS_H2EOS(b)) {
-                    off += apr_snprintf(buffer+off, bmax-off, "h2eos ");
+                    off += apr_snprintf(buffer+off, BUF_REMAIN, "h2eos ");
                 }
                 else {
-                    off += apr_snprintf(buffer+off, bmax-off, "meta(unknown) ");
+                    off += apr_snprintf(buffer+off, BUF_REMAIN, "meta(unknown) ");
                 }
             }
             else {
@@ -116,10 +118,9 @@ static void h2_conn_io_bb_log(conn_rec *
                     btype = "pool";
                 }
                 
-                off += apr_snprintf(buffer+off, bmax-off, "%s[%ld] ", 
+                off += apr_snprintf(buffer+off, BUF_REMAIN, "%s[%ld] ", 
                                     btype, 
-                                    (long)(b->length == ((apr_size_t)-1)? 
-                                           -1 : b->length));
+                                    (long)(b->length == ((apr_size_t)-1)? -1UL : b->length));
             }
         }
         line = *buffer? buffer : "(empty)";
@@ -159,7 +160,7 @@ apr_status_t h2_conn_io_init(h2_conn_io
                       "h2_conn_io(%ld): init, buffering=%d, warmup_size=%ld, "
                       "cd_secs=%f", io->c->id, io->buffer_output, 
                       (long)io->warmup_size,
-                      ((float)io->cooldown_usecs/APR_USEC_PER_SEC));
+                      ((double)io->cooldown_usecs/APR_USEC_PER_SEC));
     }
 
     return APR_SUCCESS;
@@ -208,8 +209,8 @@ static apr_status_t read_to_scratch(h2_c
         apr_bucket_file *f = (apr_bucket_file *)b->data;
         apr_file_t *fd = f->fd;
         apr_off_t offset = b->start;
-        apr_size_t len = b->length;
         
+        len = b->length;
         /* file buckets will either mmap (which we do not want) or
          * read 8000 byte chunks and split themself. However, we do
          * know *exactly* how many bytes we need where.
@@ -294,13 +295,13 @@ int h2_conn_io_needs_flush(h2_conn_io *i
 {
     if (!io->is_flushed) {
         apr_off_t len = h2_brigade_mem_size(io->output);
-        if (len > io->flush_threshold) {
+        if (len > (apr_off_t)io->flush_threshold) {
             return 1;
         }
         /* if we do not exceed flush length due to memory limits,
          * we want at least flush when we have that amount of data. */
         apr_brigade_length(io->output, 0, &len);
-        return len > (4 * io->flush_threshold);
+        return len > (apr_off_t)(4 * io->flush_threshold);
     }
     return 0;
 }

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_from_h1.c Sun Sep 26 14:30:51 2021
@@ -114,65 +114,11 @@ static void fix_vary(request_rec *r)
     }
 }
 
-static void set_basic_http_header(apr_table_t *headers, request_rec *r,
-                                  apr_pool_t *pool)
-{
-    char *date = NULL;
-    const char *proxy_date = NULL;
-    const char *server = NULL;
-    const char *us = ap_get_server_banner();
-    
-    /*
-     * keep the set-by-proxy server and date headers, otherwise
-     * generate a new server header / date header
-     */
-    if (r && r->proxyreq != PROXYREQ_NONE) {
-        proxy_date = apr_table_get(r->headers_out, "Date");
-        if (!proxy_date) {
-            /*
-             * proxy_date needs to be const. So use date for the creation of
-             * our own Date header and pass it over to proxy_date later to
-             * avoid a compiler warning.
-             */
-            date = apr_palloc(pool, APR_RFC822_DATE_LEN);
-            ap_recent_rfc822_date(date, r->request_time);
-        }
-        server = apr_table_get(r->headers_out, "Server");
-    }
-    else {
-        date = apr_palloc(pool, APR_RFC822_DATE_LEN);
-        ap_recent_rfc822_date(date, r? r->request_time : apr_time_now());
-    }
-    
-    apr_table_setn(headers, "Date", proxy_date ? proxy_date : date );
-    if (r) {
-        apr_table_unset(r->headers_out, "Date");
-    }
-    
-    if (!server && *us) {
-        server = us;
-    }
-    if (server) {
-        apr_table_setn(headers, "Server", server);
-        if (r) {
-            apr_table_unset(r->headers_out, "Server");
-        }
-    }
-}
-
-static int copy_header(void *ctx, const char *name, const char *value)
-{
-    apr_table_t *headers = ctx;
-    
-    apr_table_add(headers, name, value);
-    return 1;
-}
-
 static h2_headers *create_response(h2_task *task, request_rec *r)
 {
     const char *clheader;
     const char *ctype;
-    apr_table_t *headers;
+
     /*
      * Now that we are ready to send a response, we need to combine the two
      * header field tables into a single table.  If we don't do this, our
@@ -279,28 +225,24 @@ static h2_headers *create_response(h2_ta
         apr_table_unset(r->headers_out, "Content-Length");
     }
     
-    headers = apr_table_make(r->pool, 10);
-    
-    set_basic_http_header(headers, r, r->pool);
-    if (r->status == HTTP_NOT_MODIFIED) {
-        apr_table_do(copy_header, headers, r->headers_out,
-                     "ETag",
-                     "Content-Location",
-                     "Expires",
-                     "Cache-Control",
-                     "Vary",
-                     "Warning",
-                     "WWW-Authenticate",
-                     "Proxy-Authenticate",
-                     "Set-Cookie",
-                     "Set-Cookie2",
-                     NULL);
+    /*
+     * keep the set-by-proxy server and date headers, otherwise
+     * generate a new server header / date header
+     */
+    if (r->proxyreq != PROXYREQ_RESPONSE
+            || !apr_table_get(r->headers_out, "Date")) {
+        char *date = apr_palloc(r->pool, APR_RFC822_DATE_LEN);
+        ap_recent_rfc822_date(date, r->request_time);
+        apr_table_setn(r->headers_out, "Date", date );
     }
-    else {
-        apr_table_do(copy_header, headers, r->headers_out, NULL);
+    if (r->proxyreq != PROXYREQ_RESPONSE) {
+        const char *us = ap_get_server_banner();
+        if (us) {
+            apr_table_setn(r->headers_out, "Server", us);
+        }
     }
     
-    return h2_headers_rcreate(r, r->status, headers, r->pool);
+    return h2_headers_rcreate(r, r->status, r->headers_out, r->pool);
 }
 
 typedef enum {
@@ -669,10 +611,10 @@ static void make_chunk(h2_task *task, ap
      * to the end of the brigade. */
     char buffer[128];
     apr_bucket *c;
-    int len;
+    apr_size_t len;
     
-    len = apr_snprintf(buffer, H2_ALEN(buffer), 
-                       "%"APR_UINT64_T_HEX_FMT"\r\n", (apr_uint64_t)chunk_len);
+    len = (apr_size_t)apr_snprintf(buffer, H2_ALEN(buffer), 
+                                   "%"APR_UINT64_T_HEX_FMT"\r\n", (apr_uint64_t)chunk_len);
     c = apr_bucket_heap_create(buffer, len, NULL, bb->bucket_alloc);
     APR_BUCKET_INSERT_BEFORE(first, c);
     c = apr_bucket_heap_create("\r\n", 2, NULL, bb->bucket_alloc);

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_headers.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_headers.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_headers.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_headers.c Sun Sep 26 14:30:51 2021
@@ -113,9 +113,9 @@ apr_bucket *h2_bucket_headers_beam(struc
 }
 
 
-h2_headers *h2_headers_create(int status, apr_table_t *headers_in, 
-                                apr_table_t *notes, apr_off_t raw_bytes,
-                                apr_pool_t *pool)
+h2_headers *h2_headers_create(int status, const apr_table_t *headers_in, 
+                              const apr_table_t *notes, apr_off_t raw_bytes,
+                              apr_pool_t *pool)
 {
     h2_headers *headers = apr_pcalloc(pool, sizeof(h2_headers));
     headers->status    = status;
@@ -141,7 +141,7 @@ apr_size_t h2_headers_length(h2_headers
 }
 
 h2_headers *h2_headers_rcreate(request_rec *r, int status,
-                                 apr_table_t *header, apr_pool_t *pool)
+                               const apr_table_t *header, apr_pool_t *pool)
 {
     h2_headers *headers = h2_headers_create(status, header, r->notes, 0, pool);
     if (headers->status == HTTP_FORBIDDEN) {
@@ -172,14 +172,12 @@ h2_headers *h2_headers_rcreate(request_r
 
 h2_headers *h2_headers_copy(apr_pool_t *pool, h2_headers *h)
 {
-    return h2_headers_create(h->status, apr_table_copy(pool, h->headers), 
-                             apr_table_copy(pool, h->notes), h->raw_bytes, pool);
+    return h2_headers_create(h->status, h->headers, h->notes, h->raw_bytes, pool);
 }
 
 h2_headers *h2_headers_clone(apr_pool_t *pool, h2_headers *h)
 {
-    return h2_headers_create(h->status, apr_table_clone(pool, h->headers), 
-                             apr_table_clone(pool, h->notes), h->raw_bytes, pool);
+    return h2_headers_create(h->status, h->headers, h->notes, h->raw_bytes, pool);
 }
 
 h2_headers *h2_headers_die(apr_status_t type,

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_headers.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_headers.h?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_headers.h (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_headers.h Sun Sep 26 14:30:51 2021
@@ -44,8 +44,8 @@ apr_bucket *h2_bucket_headers_beam(struc
  * @param raw_bytes the raw network bytes (if known) used to transmit these
  * @param pool the memory pool to use
  */
-h2_headers *h2_headers_create(int status, apr_table_t *header, 
-                              apr_table_t *notes, apr_off_t raw_bytes, 
+h2_headers *h2_headers_create(int status, const apr_table_t *header,
+                              const apr_table_t *notes, apr_off_t raw_bytes,
                               apr_pool_t *pool);
 
 /**
@@ -56,7 +56,7 @@ h2_headers *h2_headers_create(int status
  * @param pool the memory pool to use
  */
 h2_headers *h2_headers_rcreate(request_rec *r, int status, 
-                                 apr_table_t *header, apr_pool_t *pool);
+                               const apr_table_t *header, apr_pool_t *pool);
 
 /**
  * Copy the headers into another pool. This will not copy any
@@ -72,7 +72,6 @@ h2_headers *h2_headers_clone(apr_pool_t
 
 /**
  * Create the headers for the given error.
- * @param stream_id id of the stream to create the headers for
  * @param type the error code
  * @param req the original h2_request
  * @param pool the memory pool to use

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_mplx.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_mplx.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_mplx.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_mplx.c Sun Sep 26 14:30:51 2021
@@ -737,6 +737,12 @@ static h2_task *s_next_stream_task(h2_mp
             return stream->task;
         }
     }
+    if (m->tasks_active >= m->limit_active && !h2_iq_empty(m->q)) {
+        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, m->c,
+                      "h2_session(%ld): delaying request processing. "
+                      "Current limit is %d and %d workers are in use.",
+                      m->id, m->limit_active, m->tasks_active);
+    }
     return NULL;
 }
 
@@ -948,7 +954,6 @@ static apr_status_t m_unschedule_slow_ta
         task->redo = 1;
         h2_task_rst(task, H2_ERR_CANCEL);
     }
-    
     return rv;
 }
 
@@ -1131,14 +1136,36 @@ int h2_mplx_m_awaits_data(h2_mplx *m)
     return waiting;
 }
 
+static int reset_is_acceptable(h2_stream *stream)
+{
+    /* client may terminate a stream via H2 RST_STREAM message at any time.
+     * This is annyoing when we have committed resources (e.g. worker threads)
+     * to it, so our mood (e.g. willingness to commit resources on this
+     * connection in the future) goes down.
+     *
+     * This is a DoS protection. We do not want to make it too easy for
+     * a client to eat up server resources.
+     *
+     * However: there are cases where a RST_STREAM is the only way to end
+     * a request. This includes websockets and server-side-event streams (SSEs).
+     * The responses to such requests continue forever otherwise.
+     *
+     */
+    if (!stream->task) return 1; /* have not started or already ended for us. acceptable. */
+    if (!(stream->id & 0x01)) return 1; /* stream initiated by us. acceptable. */
+    if (!stream->has_response) return 0; /* no response headers produced yet. bad. */
+    if (!stream->out_data_frames) return 0; /* no response body data sent yet. bad. */
+    return 1; /* otherwise, be forgiving */
+}
+
 apr_status_t h2_mplx_m_client_rst(h2_mplx *m, int stream_id)
 {
     h2_stream *stream;
     apr_status_t status = APR_SUCCESS;
-    
+
     H2_MPLX_ENTER_ALWAYS(m);
     stream = h2_ihash_get(m->streams, stream_id);
-    if (stream && stream->task) {
+    if (stream && !reset_is_acceptable(stream)) {
         status = m_be_annoyed(m);
     }
     H2_MPLX_LEAVE(m);

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_push.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_push.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_push.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_push.c Sun Sep 26 14:30:51 2021
@@ -23,7 +23,7 @@
 #include <apr_time.h>
 
 #ifdef H2_OPENSSL
-#include <openssl/sha.h>
+#include <openssl/evp.h>
 #endif
 
 #include <httpd.h>
@@ -59,7 +59,7 @@ static const char *policy_str(h2_push_po
 
 typedef struct {
     const h2_request *req;
-    int push_policy;
+    apr_uint32_t push_policy;
     apr_pool_t *pool;
     apr_array_header_t *pushes;
     const char *s;
@@ -434,7 +434,7 @@ static int head_iter(void *ctx, const ch
 }
 
 apr_array_header_t *h2_push_collect(apr_pool_t *p, const h2_request *req,
-                                    int push_policy, const h2_headers *res)
+                                    apr_uint32_t push_policy, const h2_headers *res)
 {
     if (req && push_policy != H2_PUSH_NONE) {
         /* Collect push candidates from the request/response pair.
@@ -472,27 +472,32 @@ typedef struct h2_push_diary_entry {
 
 
 #ifdef H2_OPENSSL
-static void sha256_update(SHA256_CTX *ctx, const char *s)
+static void sha256_update(EVP_MD_CTX *ctx, const char *s)
 {
-    SHA256_Update(ctx, s, strlen(s));
+    EVP_DigestUpdate(ctx, s, strlen(s));
 }
 
 static void calc_sha256_hash(h2_push_diary *diary, apr_uint64_t *phash, h2_push *push) 
 {
-    SHA256_CTX sha256;
+    EVP_MD_CTX *md;
     apr_uint64_t val;
-    unsigned char hash[SHA256_DIGEST_LENGTH];
+    unsigned char hash[EVP_MAX_MD_SIZE];
+    unsigned len;
     int i;
-    
-    SHA256_Init(&sha256);
-    sha256_update(&sha256, push->req->scheme);
-    sha256_update(&sha256, "://");
-    sha256_update(&sha256, push->req->authority);
-    sha256_update(&sha256, push->req->path);
-    SHA256_Final(hash, &sha256);
+
+    md = EVP_MD_CTX_create();
+    ap_assert(md != NULL);
+
+    i = EVP_DigestInit_ex(md, EVP_sha256(), NULL);
+    ap_assert(i == 1);
+    sha256_update(md, push->req->scheme);
+    sha256_update(md, "://");
+    sha256_update(md, push->req->authority);
+    sha256_update(md, push->req->path);
+    EVP_DigestFinal(md, hash, &len);
 
     val = 0;
-    for (i = 0; i != sizeof(val); ++i)
+    for (i = 0; i != len; ++i)
         val = val * 256 + hash[i];
     *phash = val >> (64 - diary->mask_bits);
 }
@@ -501,13 +506,14 @@ static void calc_sha256_hash(h2_push_dia
 
 static unsigned int val_apr_hash(const char *str) 
 {
-    apr_ssize_t len = strlen(str);
+    apr_ssize_t len = (apr_ssize_t)strlen(str);
     return apr_hashfunc_default(str, &len);
 }
 
 static void calc_apr_hash(h2_push_diary *diary, apr_uint64_t *phash, h2_push *push) 
 {
     apr_uint64_t val;
+    (void)diary;
 #if APR_UINT64_MAX > UINT_MAX
     val = ((apr_uint64_t)(val_apr_hash(push->req->scheme)) << 32);
     val ^= ((apr_uint64_t)(val_apr_hash(push->req->authority)) << 16);
@@ -653,7 +659,7 @@ apr_array_header_t *h2_push_diary_update
                 /* Intentional no APLOGNO */
                 ap_log_cerror(APLOG_MARK, GCSLOG_LEVEL, 0, session->c,
                               "push_diary_update: already there PUSH %s", push->req->path);
-                move_to_last(session->push_diary, idx);
+                move_to_last(session->push_diary, (apr_size_t)idx);
             }
             else {
                 /* Intentional no APLOGNO */

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_push.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_push.h?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_push.h (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_push.h Sun Sep 26 14:30:51 2021
@@ -99,7 +99,7 @@ struct h2_push_diary {
  */
 apr_array_header_t *h2_push_collect(apr_pool_t *p, 
                                     const struct h2_request *req, 
-                                    int push_policy, 
+                                    apr_uint32_t push_policy, 
                                     const struct h2_headers *res);
 
 /**

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_request.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_request.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_request.c Sun Sep 26 14:30:51 2021
@@ -210,12 +210,74 @@ h2_request *h2_request_clone(apr_pool_t
     return dst;
 }
 
+#if !AP_MODULE_MAGIC_AT_LEAST(20120211, 106)
+static request_rec *my_ap_create_request(conn_rec *c)
+{
+    apr_pool_t *p;
+    request_rec *r;
+
+    apr_pool_create(&p, c->pool);
+    apr_pool_tag(p, "request");
+    r = apr_pcalloc(p, sizeof(request_rec));
+    AP_READ_REQUEST_ENTRY((intptr_t)r, (uintptr_t)c);
+    r->pool            = p;
+    r->connection      = c;
+    r->server          = c->base_server;
+
+    r->user            = NULL;
+    r->ap_auth_type    = NULL;
+
+    r->allowed_methods = ap_make_method_list(p, 2);
+
+    r->headers_in      = apr_table_make(r->pool, 5);
+    r->trailers_in     = apr_table_make(r->pool, 5);
+    r->subprocess_env  = apr_table_make(r->pool, 25);
+    r->headers_out     = apr_table_make(r->pool, 12);
+    r->err_headers_out = apr_table_make(r->pool, 5);
+    r->trailers_out    = apr_table_make(r->pool, 5);
+    r->notes           = apr_table_make(r->pool, 5);
+
+    r->request_config  = ap_create_request_config(r->pool);
+    /* Must be set before we run create request hook */
+
+    r->proto_output_filters = c->output_filters;
+    r->output_filters  = r->proto_output_filters;
+    r->proto_input_filters = c->input_filters;
+    r->input_filters   = r->proto_input_filters;
+    ap_run_create_request(r);
+    r->per_dir_config  = r->server->lookup_defaults;
+
+    r->sent_bodyct     = 0;                      /* bytect isn't for body */
+
+    r->read_length     = 0;
+    r->read_body       = REQUEST_NO_BODY;
+
+    r->status          = HTTP_OK;  /* Until further notice */
+    r->header_only     = 0;
+    r->the_request     = NULL;
+
+    /* Begin by presuming any module can make its own path_info assumptions,
+     * until some module interjects and changes the value.
+     */
+    r->used_path_info = AP_REQ_DEFAULT_PATH_INFO;
+
+    r->useragent_addr = c->client_addr;
+    r->useragent_ip = c->client_ip;
+    return r;
+}
+#endif
+
 request_rec *h2_request_create_rec(const h2_request *req, conn_rec *c)
 {
     int access_status = HTTP_OK;    
 
+#if AP_MODULE_MAGIC_AT_LEAST(20120211, 106)
     request_rec *r = ap_create_request(c);
+#else
+    request_rec *r = my_ap_create_request(c);
+#endif
 
+#if AP_MODULE_MAGIC_AT_LEAST(20120211, 107)
     ap_run_pre_read_request(r, c);
 
     /* Time to populate r with the data we have. */
@@ -244,6 +306,49 @@ request_rec *h2_request_create_rec(const
         r->status = HTTP_OK;
         goto die;
     }
+#else
+    {
+        const char *s;
+
+        r->headers_in = apr_table_clone(r->pool, req->headers);
+        ap_run_pre_read_request(r, c);
+
+        /* Time to populate r with the data we have. */
+        r->request_time = req->request_time;
+        r->method = apr_pstrdup(r->pool, req->method);
+        /* Provide quick information about the request method as soon as known */
+        r->method_number = ap_method_number_of(r->method);
+        if (r->method_number == M_GET && r->method[0] == 'H') {
+            r->header_only = 1;
+        }
+        ap_parse_uri(r, req->path ? req->path : "");
+        r->protocol = (char*)"HTTP/2.0";
+        r->proto_num = HTTP_VERSION(2, 0);
+        r->the_request = apr_psprintf(r->pool, "%s %s HTTP/2.0",
+                                      r->method, req->path ? req->path : "");
+
+        /* Start with r->hostname = NULL, ap_check_request_header() will get it
+         * form Host: header, otherwise we get complains about port numbers.
+         */
+        r->hostname = NULL;
+        ap_update_vhost_from_headers(r);
+
+         /* we may have switched to another server */
+         r->per_dir_config = r->server->lookup_defaults;
+
+         s = apr_table_get(r->headers_in, "Expect");
+         if (s && s[0]) {
+            if (ap_cstr_casecmp(s, "100-continue") == 0) {
+                r->expecting_100 = 1;
+            }
+            else {
+                r->status = HTTP_EXPECTATION_FAILED;
+                access_status = r->status;
+                goto die;
+            }
+         }
+    }
+#endif
 
     /* we may have switched to another server */
     r->per_dir_config = r->server->lookup_defaults;

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_session.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_session.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_session.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_session.c Sun Sep 26 14:30:51 2021
@@ -73,7 +73,7 @@ static int h2_session_status_from_apr_st
     return NGHTTP2_ERR_PROTO;
 }
 
-h2_stream *h2_session_stream_get(h2_session *session, int stream_id)
+static h2_stream *get_stream(h2_session *session, int stream_id)
 {
     return nghttp2_session_get_stream_user_data(session->ngh2, stream_id);
 }
@@ -232,7 +232,7 @@ static int on_data_chunk_recv_cb(nghttp2
     h2_stream * stream;
     int rv = 0;
     
-    stream = h2_session_stream_get(session, stream_id);
+    stream = get_stream(session, stream_id);
     if (stream) {
         status = h2_stream_recv_DATA(stream, flags, data, len);
         dispatch_event(session, H2_SESSION_EV_STREAM_CHANGE, 0, "stream data rcvd");
@@ -258,7 +258,7 @@ static int on_stream_close_cb(nghttp2_se
     h2_stream *stream;
     
     (void)ngh2;
-    stream = h2_session_stream_get(session, stream_id);
+    stream = get_stream(session, stream_id);
     if (stream) {
         if (error_code) {
             ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c,
@@ -280,7 +280,7 @@ static int on_begin_headers_cb(nghttp2_s
     /* We may see HEADERs at the start of a stream or after all DATA
      * streams to carry trailers. */
     (void)ngh2;
-    s = h2_session_stream_get(session, frame->hd.stream_id);
+    s = get_stream(session, frame->hd.stream_id);
     if (s) {
         /* nop */
     }
@@ -301,7 +301,7 @@ static int on_header_cb(nghttp2_session
     apr_status_t status;
     
     (void)flags;
-    stream = h2_session_stream_get(session, frame->hd.stream_id);
+    stream = get_stream(session, frame->hd.stream_id);
     if (!stream) {
         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, APLOGNO(02920) 
                       "h2_stream(%ld-%d): on_header unknown stream",
@@ -349,14 +349,14 @@ static int on_frame_recv_cb(nghttp2_sess
             /* This can be HEADERS for a new stream, defining the request,
              * or HEADER may come after DATA at the end of a stream as in
              * trailers */
-            stream = h2_session_stream_get(session, frame->hd.stream_id);
+            stream = get_stream(session, frame->hd.stream_id);
             if (stream) {
                 rv = h2_stream_recv_frame(stream, NGHTTP2_HEADERS, frame->hd.flags, 
                     frame->hd.length + H2_FRAME_HDR_LEN);
             }
             break;
         case NGHTTP2_DATA:
-            stream = h2_session_stream_get(session, frame->hd.stream_id);
+            stream = get_stream(session, frame->hd.stream_id);
             if (stream) {
                 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c,  
                               H2_STRM_LOG(APLOGNO(02923), stream, 
@@ -390,7 +390,7 @@ static int on_frame_recv_cb(nghttp2_sess
                           "h2_stream(%ld-%d): RST_STREAM by client, error=%d",
                           session->id, (int)frame->hd.stream_id,
                           (int)frame->rst_stream.error_code);
-            stream = h2_session_stream_get(session, frame->hd.stream_id);
+            stream = get_stream(session, frame->hd.stream_id);
             if (stream && stream->initiated_on) {
                 /* A stream reset on a request we sent it. Normal, when the
                  * client does not want it. */
@@ -505,7 +505,7 @@ static int on_send_data_cb(nghttp2_sessi
     ap_assert(frame->data.padlen <= (H2_MAX_PADLEN+1));
     padlen = (unsigned char)frame->data.padlen;
     
-    stream = h2_session_stream_get(session, stream_id);
+    stream = get_stream(session, stream_id);
     if (!stream) {
         ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_NOTFOUND, session->c,
                       APLOGNO(02924) 
@@ -595,7 +595,7 @@ static int on_frame_send_cb(nghttp2_sess
                      (long)session->frames_sent);
     }
     
-    stream = h2_session_stream_get(session, stream_id);
+    stream = get_stream(session, stream_id);
     if (stream) {
         h2_stream_send_frame(stream, frame->hd.type, frame->hd.flags, 
             frame->hd.length + H2_FRAME_HDR_LEN);
@@ -620,7 +620,7 @@ static int on_invalid_header_cb(nghttp2_
                       apr_pstrndup(session->pool, (const char *)name, namelen),
                       apr_pstrndup(session->pool, (const char *)value, valuelen));
     }
-    stream = h2_session_stream_get(session, frame->hd.stream_id);
+    stream = get_stream(session, frame->hd.stream_id);
     if (stream) {
         h2_stream_rst(stream, NGHTTP2_PROTOCOL_ERROR);
     }
@@ -774,7 +774,7 @@ static apr_status_t session_cleanup(h2_s
          * connection when sending the next request, this has the effect
          * that at least this one request will fail.
          */
-        ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c,
+        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,
                       H2_SSSN_LOG(APLOGNO(03199), session, 
                       "connection disappeared without proper "
                       "goodbye, clients will be confused, should not happen"));
@@ -799,13 +799,17 @@ static apr_status_t session_pool_cleanup
     h2_session *session;
     
     if ((session = h2_ctx_get_session(c))) {
+        int mpm_state = 0;
+        int level;
+
+        ap_mpm_query(AP_MPMQ_MPM_STATE, &mpm_state);
+        level = (AP_MPMQ_STOPPING == mpm_state)? APLOG_DEBUG : APLOG_WARNING;
         /* if the session is still there, now is the last chance
          * to perform cleanup. Normally, cleanup should have happened
-         * earlier in the connection pre_close. Main reason is that
-         * any ongoing requests on secondary connections might still access
-         * data which has, at this time, already been freed. An example
-         * is mod_ssl that uses request hooks. */
-        ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c,
+         * earlier in the connection pre_close.
+         * However, when the server is stopping, it may shutdown connections
+         * without running the pre_close hooks. Do not want about that. */
+        ap_log_cerror(APLOG_MARK, level, 0, c,
                       H2_SSSN_LOG(APLOGNO(10020), session, 
                       "session cleanup triggered by pool cleanup. "
                       "this should have happened earlier already."));
@@ -1101,7 +1105,7 @@ static ssize_t stream_data_cb(nghttp2_se
     (void)ng2s;
     (void)buf;
     (void)source;
-    stream = h2_session_stream_get(session, stream_id);
+    stream = get_stream(session, stream_id);
     if (!stream) {
         ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, session->c,
                       APLOGNO(02937) 
@@ -1550,7 +1554,7 @@ static void h2_session_in_flush(h2_sessi
     int id;
     
     while ((id = h2_iq_shift(session->in_process)) > 0) {
-        h2_stream *stream = h2_session_stream_get(session, id);
+        h2_stream *stream = get_stream(session, id);
         if (stream) {
             ap_assert(!stream->scheduled);
             if (h2_stream_prep_processing(stream) == APR_SUCCESS) {
@@ -1563,7 +1567,7 @@ static void h2_session_in_flush(h2_sessi
     }
 
     while ((id = h2_iq_shift(session->in_pending)) > 0) {
-        h2_stream *stream = h2_session_stream_get(session, id);
+        h2_stream *stream = get_stream(session, id);
         if (stream) {
             h2_stream_flush_input(stream);
         }
@@ -1713,8 +1717,8 @@ static void transit(h2_session *session,
                     timeout = session->s->timeout;
                     update_child_status(session, SERVER_BUSY_READ, "idle");
                     ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c, 
-                                  H2_SSSN_LOG("", session, "enter idle, timeout = %d sec"), 
-                                  (int)apr_time_sec(H2MAX(session->s->timeout, session->s->keep_alive_timeout)));
+                                  H2_SSSN_LOG("", session, "enter idle, timeout = %d sec"),
+                                  (int)apr_time_sec(timeout));
                 }
                 else if (session->open_streams) {
                     s = "timeout";
@@ -1908,6 +1912,9 @@ static void h2_session_ev_mpm_stopping(h
             break;
         default:
             h2_session_shutdown_notice(session);
+#if !AP_MODULE_MAGIC_AT_LEAST(20120211, 110)
+            h2_workers_graceful_shutdown(session->workers);
+#endif
             break;
     }
 }

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_session.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_session.h?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_session.h (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_session.h Sun Sep 26 14:30:51 2021
@@ -188,11 +188,6 @@ void h2_session_close(h2_session *sessio
 int h2_session_push_enabled(h2_session *session);
 
 /**
- * Look up the stream in this session with the given id.
- */
-struct h2_stream *h2_session_stream_get(h2_session *session, int stream_id);
-
-/**
  * Submit a push promise on the stream and schedule the new steam for
  * processing..
  * 

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_task.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_task.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_task.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_task.c Sun Sep 26 14:30:51 2021
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+ 
 #include <assert.h>
 #include <stddef.h>
 
@@ -541,6 +541,7 @@ h2_task *h2_task_create(conn_rec *second
 void h2_task_destroy(h2_task *task)
 {
     if (task->output.beam) {
+        h2_beam_log(task->output.beam, task->c, APLOG_TRACE2, "task_destroy");
         h2_beam_destroy(task->output.beam);
         task->output.beam = NULL;
     }
@@ -592,7 +593,7 @@ apr_status_t h2_task_do(h2_task *task, a
          * configurations by mod_h2 alone. 
          */
         task->c->id = (c->master->id << 8)^worker_id;
-        task->id = apr_psprintf(task->pool, "%ld-%d", c->master->id, 
+        task->id = apr_psprintf(task->pool, "%ld-%d", task->mplx->id,
                                 task->stream_id);
     }
         

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_task.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_task.h?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_task.h (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_task.h Sun Sep 26 14:30:51 2021
@@ -21,7 +21,7 @@
 
 /**
  * A h2_task fakes a HTTP/1.1 request from the data in a HTTP/2 stream 
- * (HEADER+CONT.+DATA) the module recieves.
+ * (HEADER+CONT.+DATA) the module receives.
  *
  * In order to answer a HTTP/2 stream, we want all Apache httpd infrastructure
  * to be involved as usual, as if this stream can as a separate HTTP/1.1
@@ -112,7 +112,7 @@ void h2_task_rst(h2_task *task, int erro
 
 void h2_task_register_hooks(void);
 /*
- * One time, post config intialization.
+ * One time, post config initialization.
  */
 apr_status_t h2_task_init(apr_pool_t *pool, server_rec *s);
 

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_util.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_util.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_util.c Sun Sep 26 14:30:51 2021
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+ 
 #include <assert.h>
 #include <apr_strings.h>
 #include <apr_thread_mutex.h>
@@ -425,7 +425,7 @@ void h2_iq_clear(h2_iqueue *q)
 void h2_iq_sort(h2_iqueue *q, h2_iq_cmp *cmp, void *ctx)
 {
     /* Assume that changes in ordering are minimal. This needs,
-     * best case, q->nelts - 1 comparisions to check that nothing
+     * best case, q->nelts - 1 comparisons to check that nothing
      * changed.
      */
     if (q->nelts > 0) {

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_version.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_version.h?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_version.h (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_version.h Sun Sep 26 14:30:51 2021
@@ -27,7 +27,7 @@
  * @macro
  * Version number of the http2 module as c string
  */
-#define MOD_HTTP2_VERSION "1.15.18"
+#define MOD_HTTP2_VERSION "1.15.24"
 
 /**
  * @macro
@@ -35,7 +35,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 0x010f12
+#define MOD_HTTP2_VERSION_NUM 0x010f18
 
 
 #endif /* mod_h2_h2_version_h */

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_workers.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_workers.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_workers.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_workers.c Sun Sep 26 14:30:51 2021
@@ -41,6 +41,7 @@ struct h2_slot {
     apr_thread_t *thread;
     apr_thread_mutex_t *lock;
     apr_thread_cond_t *not_idle;
+    volatile apr_uint32_t timed_out;
 };
 
 static h2_slot *pop_slot(h2_slot *volatile *phead) 
@@ -71,47 +72,47 @@ static void push_slot(h2_slot *volatile
 }
 
 static void* APR_THREAD_FUNC slot_run(apr_thread_t *thread, void *wctx);
+static void slot_done(h2_slot *slot);
 
 static apr_status_t activate_slot(h2_workers *workers, h2_slot *slot) 
 {
-    apr_status_t status;
+    apr_status_t rv;
     
     slot->workers = workers;
     slot->task = NULL;
 
+    apr_thread_mutex_lock(workers->lock);
     if (!slot->lock) {
-        status = apr_thread_mutex_create(&slot->lock,
+        rv = apr_thread_mutex_create(&slot->lock,
                                          APR_THREAD_MUTEX_DEFAULT,
                                          workers->pool);
-        if (status != APR_SUCCESS) {
-            push_slot(&workers->free, slot);
-            return status;
-        }
+        if (rv != APR_SUCCESS) goto cleanup;
     }
 
     if (!slot->not_idle) {
-        status = apr_thread_cond_create(&slot->not_idle, workers->pool);
-        if (status != APR_SUCCESS) {
-            push_slot(&workers->free, slot);
-            return status;
-        }
+        rv = apr_thread_cond_create(&slot->not_idle, workers->pool);
+        if (rv != APR_SUCCESS) goto cleanup;
     }
     
-    ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, workers->s,
+    ap_log_error(APLOG_MARK, APLOG_TRACE3, 0, workers->s,
                  "h2_workers: new thread for slot %d", slot->id); 
 
     /* thread will either immediately start work or add itself
      * to the idle queue */
     apr_atomic_inc32(&workers->worker_count);
-    status = apr_thread_create(&slot->thread, workers->thread_attr,
+    slot->timed_out = 0;
+    rv = apr_thread_create(&slot->thread, workers->thread_attr,
                                slot_run, slot, workers->pool);
-    if (status != APR_SUCCESS) {
+    if (rv != APR_SUCCESS) {
         apr_atomic_dec32(&workers->worker_count);
+    }
+
+cleanup:
+    apr_thread_mutex_unlock(workers->lock);
+    if (rv != APR_SUCCESS) {
         push_slot(&workers->free, slot);
-        return status;
     }
-    
-    return APR_SUCCESS;
+    return rv;
 }
 
 static apr_status_t add_worker(h2_workers *workers)
@@ -127,11 +128,19 @@ static void wake_idle_worker(h2_workers
 {
     h2_slot *slot = pop_slot(&workers->idle);
     if (slot) {
+        int timed_out = 0;
         apr_thread_mutex_lock(slot->lock);
-        apr_thread_cond_signal(slot->not_idle);
+        timed_out = slot->timed_out;
+        if (!timed_out) {
+            apr_thread_cond_signal(slot->not_idle);
+        }
         apr_thread_mutex_unlock(slot->lock);
+        if (timed_out) {
+            slot_done(slot);
+            wake_idle_worker(workers);
+        }
     }
-    else if (workers->dynamic) {
+    else if (workers->dynamic && !workers->shutdown) {
         add_worker(workers);
     }
 }
@@ -185,13 +194,18 @@ static h2_fifo_op_t mplx_peek(void *head
 static int get_next(h2_slot *slot)
 {
     h2_workers *workers = slot->workers;
+    int non_essential = slot->id >= workers->min_workers;
+    apr_status_t rv;
 
-    while (!workers->aborted) {
+    while (!workers->aborted && !slot->timed_out) {
         ap_assert(slot->task == NULL);
+        if (non_essential && workers->shutdown) {
+            /* Terminate non-essential worker on shutdown */
+            break;
+        }
         if (h2_fifo_try_peek(workers->mplxs, mplx_peek, slot) == APR_EOF) {
             /* The queue is terminated with the MPM child being cleaned up,
-             * just leave.
-             */
+             * just leave. */
             break;
         }
         if (slot->task) {
@@ -202,8 +216,18 @@ static int get_next(h2_slot *slot)
 
         apr_thread_mutex_lock(slot->lock);
         if (!workers->aborted) {
+
             push_slot(&workers->idle, slot);
-            apr_thread_cond_wait(slot->not_idle, slot->lock);
+            if (non_essential && workers->max_idle_duration) {
+                rv = apr_thread_cond_timedwait(slot->not_idle, slot->lock,
+                                               workers->max_idle_duration);
+                if (APR_TIMEUP == rv) {
+                    slot->timed_out = 1;
+                }
+            }
+            else {
+                apr_thread_cond_wait(slot->not_idle, slot->lock);
+            }
         }
         apr_thread_mutex_unlock(slot->lock);
     }
@@ -251,17 +275,36 @@ static void* APR_THREAD_FUNC slot_run(ap
         } while (slot->task);
     }
 
-    slot_done(slot);
+    if (!slot->timed_out) {
+        slot_done(slot);
+    }
 
     apr_thread_exit(thread, APR_SUCCESS);
     return NULL;
 }
 
-static apr_status_t workers_pool_cleanup(void *data)
+static void wake_non_essential_workers(h2_workers *workers)
 {
-    h2_workers *workers = data;
     h2_slot *slot;
-    
+    /* pop all idle, signal the non essentials and add the others again */
+    if ((slot = pop_slot(&workers->idle))) {
+        wake_non_essential_workers(workers);
+        if (slot->id > workers->min_workers) {
+            apr_thread_mutex_lock(slot->lock);
+            apr_thread_cond_signal(slot->not_idle);
+            apr_thread_mutex_unlock(slot->lock);
+        }
+        else {
+            push_slot(&workers->idle, slot);
+        }
+    }
+}
+
+static void workers_abort_idle(h2_workers *workers)
+{
+    h2_slot *slot;
+
+    workers->shutdown = 1;
     workers->aborted = 1;
     h2_fifo_term(workers->mplxs);
 
@@ -271,14 +314,49 @@ static apr_status_t workers_pool_cleanup
         apr_thread_cond_signal(slot->not_idle);
         apr_thread_mutex_unlock(slot->lock);
     }
+}
 
-    /* wait for all the workers to become zombies and join them */
+static apr_status_t workers_pool_cleanup(void *data)
+{
+    h2_workers *workers = data;
+    apr_time_t end, timeout = apr_time_from_sec(1);
+    apr_status_t rv;
+    int n, wait_sec = 5;
+
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, workers->s,
+                 "h2_workers: cleanup %d workers idling",
+                 (int)apr_atomic_read32(&workers->worker_count));
+    workers_abort_idle(workers);
+
+    /* wait for all the workers to become zombies and join them.
+     * this gets called after the mpm shuts down and all connections
+     * have either been handled (graceful) or we are forced exiting
+     * (ungrateful). Either way, we show limited patience. */
     apr_thread_mutex_lock(workers->lock);
-    if (apr_atomic_read32(&workers->worker_count)) {
-        apr_thread_cond_wait(workers->all_done, workers->lock);
+    end = apr_time_now() + apr_time_from_sec(wait_sec);
+    while ((n = apr_atomic_read32(&workers->worker_count)) > 0
+           && apr_time_now() < end) {
+        rv = apr_thread_cond_timedwait(workers->all_done, workers->lock, timeout);
+        if (APR_TIMEUP == rv) {
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, workers->s,
+                         APLOGNO(10290) "h2_workers: waiting for idle workers to close, "
+                         "still seeing %d workers living",
+                         apr_atomic_read32(&workers->worker_count));
+            continue;
+        }
+    }
+    if (n) {
+        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, workers->s,
+                     APLOGNO(10291) "h2_workers: cleanup, %d idle workers "
+                     "did not exit after %d seconds.",
+                     n, wait_sec);
     }
     apr_thread_mutex_unlock(workers->lock);
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, workers->s,
+                 "h2_workers: cleanup all workers terminated");
     join_zombies(workers);
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, workers->s,
+                 "h2_workers: cleanup zombie workers joined");
 
     return APR_SUCCESS;
 }
@@ -287,7 +365,7 @@ h2_workers *h2_workers_create(server_rec
                               int min_workers, int max_workers,
                               int idle_secs)
 {
-    apr_status_t status;
+    apr_status_t rv;
     h2_workers *workers;
     apr_pool_t *pool;
     int i, n;
@@ -311,8 +389,12 @@ h2_workers *h2_workers_create(server_rec
     workers->pool = pool;
     workers->min_workers = min_workers;
     workers->max_workers = max_workers;
-    workers->max_idle_secs = (idle_secs > 0)? idle_secs : 10;
+    workers->max_idle_duration = apr_time_from_sec((idle_secs > 0)? idle_secs : 10);
 
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, workers->s,
+                 "h2_workers: created with min=%d max=%d idle_timeout=%d sec",
+                 workers->min_workers, workers->max_workers,
+                 (int)apr_time_sec(workers->max_idle_duration));
     /* FIXME: the fifo set we use here has limited capacity. Once the
      * set is full, connections with new requests do a wait. Unfortunately,
      * we have optimizations in place there that makes such waiting "unfair"
@@ -324,16 +406,12 @@ h2_workers *h2_workers_create(server_rec
      * For now, we just make enough room to have many connections inside one
      * process.
      */
-    status = h2_fifo_set_create(&workers->mplxs, pool, 8 * 1024);
-    if (status != APR_SUCCESS) {
-        return NULL;
-    }
-    
-    status = apr_threadattr_create(&workers->thread_attr, workers->pool);
-    if (status != APR_SUCCESS) {
-        return NULL;
-    }
-    
+    rv = h2_fifo_set_create(&workers->mplxs, pool, 8 * 1024);
+    if (rv != APR_SUCCESS) goto cleanup;
+
+    rv = apr_threadattr_create(&workers->thread_attr, workers->pool);
+    if (rv != APR_SUCCESS) goto cleanup;
+
     if (ap_thread_stacksize != 0) {
         apr_threadattr_stacksize_set(workers->thread_attr,
                                      ap_thread_stacksize);
@@ -342,38 +420,39 @@ h2_workers *h2_workers_create(server_rec
                      (long)ap_thread_stacksize);
     }
     
-    status = apr_thread_mutex_create(&workers->lock,
-                                     APR_THREAD_MUTEX_DEFAULT,
-                                     workers->pool);
-    if (status == APR_SUCCESS) {        
-        status = apr_thread_cond_create(&workers->all_done, workers->pool);
-    }
-    if (status == APR_SUCCESS) {        
-        n = workers->nslots = workers->max_workers;
-        workers->slots = apr_pcalloc(workers->pool, n * sizeof(h2_slot));
-        if (workers->slots == NULL) {
-            workers->nslots = 0;
-            status = APR_ENOMEM;
-        }
-        for (i = 0; i < n; ++i) {
-            workers->slots[i].id = i;
-        }
-    }
-    if (status == APR_SUCCESS) {
-        /* we activate all for now, TODO: support min_workers again.
-         * do this in reverse for vanity reasons so slot 0 will most
-         * likely be at head of idle queue. */
-        n = workers->max_workers;
-        for (i = n-1; i >= 0; --i) {
-            status = activate_slot(workers, &workers->slots[i]);
-        }
-        /* the rest of the slots go on the free list */
-        for(i = n; i < workers->nslots; ++i) {
-            push_slot(&workers->free, &workers->slots[i]);
-        }
-        workers->dynamic = (workers->worker_count < workers->max_workers);
+    rv = apr_thread_mutex_create(&workers->lock,
+                                 APR_THREAD_MUTEX_DEFAULT,
+                                 workers->pool);
+    if (rv != APR_SUCCESS) goto cleanup;
+    rv = apr_thread_cond_create(&workers->all_done, workers->pool);
+    if (rv != APR_SUCCESS) goto cleanup;
+
+    n = workers->nslots = workers->max_workers;
+    workers->slots = apr_pcalloc(workers->pool, n * sizeof(h2_slot));
+    if (workers->slots == NULL) {
+        n = workers->nslots = 0;
+        rv = APR_ENOMEM;
+        goto cleanup;
+    }
+    for (i = 0; i < n; ++i) {
+        workers->slots[i].id = i;
+    }
+    /* we activate all for now, TODO: support min_workers again.
+     * do this in reverse for vanity reasons so slot 0 will most
+     * likely be at head of idle queue. */
+    n = workers->min_workers;
+    for (i = n-1; i >= 0; --i) {
+        rv = activate_slot(workers, &workers->slots[i]);
+        if (rv != APR_SUCCESS) goto cleanup;
+    }
+    /* the rest of the slots go on the free list */
+    for(i = n; i < workers->nslots; ++i) {
+        push_slot(&workers->free, &workers->slots[i]);
     }
-    if (status == APR_SUCCESS) {
+    workers->dynamic = (workers->worker_count < workers->max_workers);
+
+cleanup:
+    if (rv == APR_SUCCESS) {
         /* Stop/join the workers threads when the MPM child exits (pchild is
          * destroyed), and as a pre_cleanup of pchild thus before the threads
          * pools (children of workers->pool) so that they are not destroyed
@@ -396,3 +475,12 @@ apr_status_t h2_workers_unregister(h2_wo
 {
     return h2_fifo_remove(workers->mplxs, m);
 }
+
+void h2_workers_graceful_shutdown(h2_workers *workers)
+{
+    workers->shutdown = 1;
+    workers->min_workers = 1;
+    workers->max_idle_duration = apr_time_from_sec(1);
+    h2_fifo_term(workers->mplxs);
+    wake_non_essential_workers(workers);
+}

Modified: httpd/httpd/branches/2.4.x/modules/http2/h2_workers.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/h2_workers.h?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/h2_workers.h (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/h2_workers.h Sun Sep 26 14:30:51 2021
@@ -38,11 +38,12 @@ struct h2_workers {
     apr_pool_t *pool;
     
     int next_worker_id;
-    int min_workers;
-    int max_workers;
-    int max_idle_secs;
+    apr_uint32_t max_workers;
+    volatile apr_uint32_t min_workers; /* is changed during graceful shutdown */
+    volatile apr_interval_time_t max_idle_duration; /* is changed during graceful shutdown */
     
     volatile int aborted;
+    volatile int shutdown;
     int dynamic;
 
     apr_threadattr_t *thread_attr;
@@ -80,4 +81,9 @@ apr_status_t h2_workers_register(h2_work
  */
 apr_status_t h2_workers_unregister(h2_workers *workers, struct h2_mplx *m);
 
+/**
+ *  Shut down processing gracefully by terminating all idle workers.
+ */
+void h2_workers_graceful_shutdown(h2_workers *workers);
+
 #endif /* defined(__mod_h2__h2_workers__) */

Modified: httpd/httpd/branches/2.4.x/modules/http2/mod_http2.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/mod_http2.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/mod_http2.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/mod_http2.c Sun Sep 26 14:30:51 2021
@@ -24,6 +24,7 @@
 #include <http_protocol.h>
 #include <http_request.h>
 #include <http_log.h>
+#include <mpm_common.h>
 
 #include "mod_http2.h"
 
@@ -228,7 +229,9 @@ static void h2_hooks(apr_pool_t *pool)
     /* Run once after a child process has been created.
      */
     ap_hook_child_init(h2_child_init, NULL, NULL, APR_HOOK_MIDDLE);
-
+#if AP_MODULE_MAGIC_AT_LEAST(20120211, 110)
+    ap_hook_child_stopping(h2_conn_child_stopping, NULL, NULL, APR_HOOK_MIDDLE);
+#endif
     h2_h2_register_hooks();
     h2_switch_register_hooks();
     h2_task_register_hooks();

Modified: httpd/httpd/branches/2.4.x/modules/http2/mod_proxy_http2.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http2/mod_proxy_http2.c?rev=1893658&r1=1893657&r2=1893658&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http2/mod_proxy_http2.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http2/mod_proxy_http2.c Sun Sep 26 14:30:51 2021
@@ -397,18 +397,9 @@ run_connect:
     
     if (!ctx->p_conn->data && ctx->is_ssl) {
         /* New SSL connection: set a note on the connection about what
-         * protocol we want.
-         */
+         * protocol we need. */
         apr_table_setn(ctx->p_conn->connection->notes,
                        "proxy-request-alpn-protos", "h2");
-        if (ctx->p_conn->ssl_hostname) {
-            ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, ctx->owner,
-                          "set SNI to %s for (%s)",
-                          ctx->p_conn->ssl_hostname,
-                          ctx->p_conn->hostname);
-            apr_table_setn(ctx->p_conn->connection->notes,
-                           "proxy-request-hostname", ctx->p_conn->ssl_hostname);
-        }
     }
 
     if (ctx->master->aborted) goto cleanup;