]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
mod_http2: use a mutex for mplx and slave connections's allocator to be safe
authorYann Ylavic <ylavic@apache.org>
Mon, 20 Feb 2017 13:41:59 +0000 (13:41 +0000)
committerYann Ylavic <ylavic@apache.org>
Mon, 20 Feb 2017 13:41:59 +0000 (13:41 +0000)
with concurrent creation and destruction of their subpools.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1783756 13f79535-47bb-0310-9956-ffa450edef68

modules/http2/h2_conn.c
modules/http2/h2_mplx.c

index b13d47f83fb4fb826feea20a8831216f0b725c35..a8de28425b3cd2ab78bcfd7aa4f758e56ea8ea5f 100644 (file)
@@ -26,6 +26,8 @@
 #include <http_protocol.h>
 #include <http_request.h>
 
+#include <mpm_common.h>
+
 #include "h2_private.h"
 #include "h2.h"
 #include "h2_config.h"
@@ -253,6 +255,8 @@ apr_status_t h2_conn_pre_close(struct h2_ctx *ctx, conn_rec *c)
 conn_rec *h2_slave_create(conn_rec *master, int slave_id, apr_pool_t *parent)
 {
     apr_allocator_t *allocator;
+    apr_thread_mutex_t *mutex;
+    apr_status_t status;
     apr_pool_t *pool;
     conn_rec *c;
     void *cfg;
@@ -265,18 +269,30 @@ conn_rec *h2_slave_create(conn_rec *master, int slave_id, apr_pool_t *parent)
     /* We create a pool with its own allocator to be used for
      * processing a request. This is the only way to have the processing
      * independant of its parent pool in the sense that it can work in
-     * another thread.
+     * another thread. Also, the new allocator needs its own mutex to
+     * synchronize sub-pools.
      */
     apr_allocator_create(&allocator);
+    apr_allocator_max_free_set(allocator, ap_max_mem_free);
     apr_pool_create_ex(&pool, parent, NULL, allocator);
     apr_pool_tag(pool, "h2_slave_conn");
     apr_allocator_owner_set(allocator, pool);
-
+    status = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, pool);
+    if (status != APR_SUCCESS) {
+        ap_log_cerror(APLOG_MARK, APLOG_ERR, status, master, 
+                      APLOGNO() "h2_session(%ld-%d): create slave mutex",
+                      master->id, slave_id);
+        apr_pool_destroy(pool);
+        return NULL;
+    }
+    apr_allocator_mutex_set(allocator, mutex);
     c = (conn_rec *) apr_palloc(pool, sizeof(conn_rec));
     if (c == NULL) {
         ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_ENOMEM, master, 
                       APLOGNO(02913) "h2_session(%ld-%d): create slave",
                       master->id, slave_id);
+        apr_pool_destroy(pool);
         return NULL;
     }
     
index 5f3a0d0635a441417a065a56ad4a948f60094b87..ad2342b61e56daed067ed01cd69349557194729f 100644 (file)
@@ -27,6 +27,8 @@
 #include <http_core.h>
 #include <http_log.h>
 
+#include <mpm_common.h>
+
 #include "mod_http2.h"
 
 #include "h2.h"
@@ -232,35 +234,53 @@ h2_mplx *h2_mplx_create(conn_rec *c, apr_pool_t *parent,
                         h2_workers *workers)
 {
     apr_status_t status = APR_SUCCESS;
-    apr_allocator_t *allocator = NULL;
+    apr_allocator_t *allocator;
+    apr_thread_mutex_t *mutex;
     h2_mplx *m;
     ap_assert(conf);
     
-    status = apr_allocator_create(&allocator);
-    if (status != APR_SUCCESS) {
-        return NULL;
-    }
-
     m = apr_pcalloc(parent, sizeof(h2_mplx));
     if (m) {
         m->id = c->id;
         APR_RING_ELEM_INIT(m, link);
         m->c = c;
+
+        /* We create a pool with its own allocator to be used for
+         * processing slave connections. This is the only way to have the
+         * processing independant of its parent pool in the sense that it
+         * can work in another thread. Also, the new allocator needs its own
+         * mutex to synchronize sub-pools.
+         */
+        status = apr_allocator_create(&allocator);
+        if (status != APR_SUCCESS) {
+            return NULL;
+        }
+        apr_allocator_max_free_set(allocator, ap_max_mem_free);
         apr_pool_create_ex(&m->pool, parent, NULL, allocator);
         if (!m->pool) {
+            apr_allocator_destroy(allocator);
             return NULL;
         }
         apr_pool_tag(m->pool, "h2_mplx");
         apr_allocator_owner_set(allocator, m->pool);
-        
+        status = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT,
+                                         m->pool);
+        if (status != APR_SUCCESS) {
+            apr_pool_destroy(m->pool);
+            return NULL;
+        }
+        apr_allocator_mutex_set(allocator, mutex);
+
         status = apr_thread_mutex_create(&m->lock, APR_THREAD_MUTEX_DEFAULT,
                                          m->pool);
         if (status != APR_SUCCESS) {
+            apr_pool_destroy(m->pool);
             return NULL;
         }
         
         status = apr_thread_cond_create(&m->task_thawed, m->pool);
         if (status != APR_SUCCESS) {
+            apr_pool_destroy(m->pool);
             return NULL;
         }