core: Apply ap_max_mem_free to created threads' pool allocator.

Since APR does not set the threshold above which the allocator of the thread's
starts returning its memory to the system, so set ap_max_mem_free from
ap_thread_create(), ap_thread_main_create() and ap_thread_current_create().

* include/httpd.h:
  Provide our own ap_thread_create() in any case (but !APR_HAS_THREADS).
  Simplify #ifdef-ery.

* server/util.c(thread_start, ap_thread_main_create, ap_thread_current_create):
  Set ap_max_mem_free to the thread's pool allocator.
  Simplify #ifdef-ery.



git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1902728 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/include/httpd.h b/include/httpd.h
index a4c3253..1ef0021 100644
--- a/include/httpd.h
+++ b/include/httpd.h
@@ -2571,27 +2571,35 @@
 
 #if APR_HAS_THREADS
 
-#if APR_VERSION_AT_LEAST(1,8,0) && !defined(AP_NO_THREAD_LOCAL)
+/* apr_thread_create() wrapper that handles thread pool limits and
+ * ap_thread_current() eventually (if not handle by APR already).
+ */
+AP_DECLARE(apr_status_t) ap_thread_create(apr_thread_t **thread, 
+                                          apr_threadattr_t *attr, 
+                                          apr_thread_start_t func, 
+                                          void *data, apr_pool_t *pool);
+
+/* Make the main() thread ap_thread_current()-able. */
+AP_DECLARE(apr_status_t) ap_thread_main_create(apr_thread_t **thread,
+                                               apr_pool_t *pool);
+
+#if APR_VERSION_AT_LEAST(1,8,0)
 
 /**
- * APR 1.8+ implement those already.
+ * Use APR 1.8+ implementation.
  */
-#if APR_HAS_THREAD_LOCAL
-#define AP_HAS_THREAD_LOCAL 1
-#define AP_THREAD_LOCAL     APR_THREAD_LOCAL
-#else
-#define AP_HAS_THREAD_LOCAL 0
+#if APR_HAS_THREAD_LOCAL && !defined(AP_NO_THREAD_LOCAL)
+#define AP_THREAD_LOCAL                 APR_THREAD_LOCAL
 #endif
-#define ap_thread_create                apr_thread_create
 #define ap_thread_current               apr_thread_current
 #define ap_thread_current_create        apr_thread_current_create
 #define ap_thread_current_after_fork    apr_thread_current_after_fork
 
-#else /* APR_VERSION_AT_LEAST(1,8,0) && !defined(AP_NO_THREAD_LOCAL) */
+#else /* APR_VERSION_AT_LEAST(1,8,0) */
 
-#ifndef AP_NO_THREAD_LOCAL
+#if !defined(AP_NO_THREAD_LOCAL)
 /**
- * AP_THREAD_LOCAL keyword mapping the compiler's.
+ * AP_THREAD_LOCAL keyword aliases the compiler's.
  */
 #if defined(__cplusplus) && __cplusplus >= 201103L
 #define AP_THREAD_LOCAL thread_local
@@ -2604,18 +2612,7 @@
 #elif defined(WIN32) && defined(_MSC_VER)
 #define AP_THREAD_LOCAL __declspec(thread)
 #endif
-#endif /* ndef AP_NO_THREAD_LOCAL */
-
-#ifndef AP_THREAD_LOCAL
-#define AP_HAS_THREAD_LOCAL 0
-#define ap_thread_create apr_thread_create
-#else /* AP_THREAD_LOCAL */
-#define AP_HAS_THREAD_LOCAL 1
-AP_DECLARE(apr_status_t) ap_thread_create(apr_thread_t **thread, 
-                                          apr_threadattr_t *attr, 
-                                          apr_thread_start_t func, 
-                                          void *data, apr_pool_t *pool);
-#endif /* AP_THREAD_LOCAL */
+#endif /* !defined(AP_NO_THREAD_LOCAL) */
 
 AP_DECLARE(apr_status_t) ap_thread_current_create(apr_thread_t **current,
                                                   apr_threadattr_t *attr,
@@ -2623,17 +2620,16 @@
 AP_DECLARE(void) ap_thread_current_after_fork(void);
 AP_DECLARE(apr_thread_t *) ap_thread_current(void);
 
-#endif /* APR_VERSION_AT_LEAST(1,8,0) && !defined(AP_NO_THREAD_LOCAL) */
-
-AP_DECLARE(apr_status_t) ap_thread_main_create(apr_thread_t **thread,
-                                               apr_pool_t *pool);
-
-#else  /* APR_HAS_THREADS */
-
-#define AP_HAS_THREAD_LOCAL 0
+#endif /* APR_VERSION_AT_LEAST(1,8,0) */
 
 #endif /* APR_HAS_THREADS */
 
+#ifdef AP_THREAD_LOCAL
+#define AP_HAS_THREAD_LOCAL 1
+#else
+#define AP_HAS_THREAD_LOCAL 0
+#endif
+
 /**
  * Get server load params
  * @param ld struct to populate: -1 in fields means error
diff --git a/server/util.c b/server/util.c
index cc0adbc..63c5132 100644
--- a/server/util.c
+++ b/server/util.c
@@ -69,6 +69,7 @@
 #endif
 
 #include "ap_mpm.h"
+#include "mpm_common.h"         /* for ap_max_mem_free */
 
 /* A bunch of functions in util.c scan strings looking for certain characters.
  * To make that more efficient we encode a lookup table.  The test_char_table
@@ -3285,26 +3286,27 @@
 
 #if APR_HAS_THREADS
 
-#if APR_VERSION_AT_LEAST(1,8,0) && !defined(AP_NO_THREAD_LOCAL)
-
-#define ap_thread_current_create apr_thread_current_create
-
-#else /* APR_VERSION_AT_LEAST(1,8,0) && !defined(AP_NO_THREAD_LOCAL) */
-
-#if AP_HAS_THREAD_LOCAL
+#if AP_HAS_THREAD_LOCAL && !APR_VERSION_AT_LEAST(1,8,0)
+AP_THREAD_LOCAL static apr_thread_t *current_thread = NULL;
+#endif
 
 struct thread_ctx {
     apr_thread_start_t func;
     void *data;
 };
 
-static AP_THREAD_LOCAL apr_thread_t *current_thread = NULL;
-
 static void *APR_THREAD_FUNC thread_start(apr_thread_t *thread, void *data)
 {
     struct thread_ctx *ctx = data;
+    apr_pool_t *tp = apr_thread_pool_get(thread);
 
+    /* Don't let the thread's pool allocator with no limits */
+    apr_allocator_max_free_set(apr_pool_allocator_get(tp),
+                               ap_max_mem_free);
+
+#if AP_HAS_THREAD_LOCAL && !APR_VERSION_AT_LEAST(1,8,0)
     current_thread = thread;
+#endif
     return ctx->func(thread, ctx->data);
 }
 
@@ -3320,67 +3322,6 @@
     return apr_thread_create(thread, attr, thread_start, ctx, pool);
 }
 
-#endif /* AP_HAS_THREAD_LOCAL */
-
-AP_DECLARE(apr_status_t) ap_thread_current_create(apr_thread_t **current,
-                                                  apr_threadattr_t *attr,
-                                                  apr_pool_t *pool)
-{
-    apr_status_t rv;
-    apr_abortfunc_t abort_fn = apr_pool_abort_get(pool);
-    apr_allocator_t *allocator;
-    apr_os_thread_t osthd;
-    apr_pool_t *p;
-
-    *current = ap_thread_current();
-    if (*current) {
-        return APR_EEXIST;
-    }
-
-    rv = apr_allocator_create(&allocator);
-    if (rv != APR_SUCCESS) {
-        if (abort_fn)
-            abort_fn(rv);
-        return rv;
-    }
-    rv = apr_pool_create_unmanaged_ex(&p, abort_fn, allocator);
-    if (rv != APR_SUCCESS) {
-        apr_allocator_destroy(allocator);
-        return rv;
-    }
-    apr_allocator_owner_set(allocator, p);
-
-    osthd = apr_os_thread_current();
-    rv = apr_os_thread_put(current, &osthd, p);
-    if (rv != APR_SUCCESS) {
-        apr_pool_destroy(p);
-        return rv;
-    }
-
-#if AP_HAS_THREAD_LOCAL
-    current_thread = *current;
-#endif
-    return APR_SUCCESS;
-}
-
-AP_DECLARE(void) ap_thread_current_after_fork(void)
-{
-#if AP_HAS_THREAD_LOCAL
-    current_thread = NULL;
-#endif
-}
-
-AP_DECLARE(apr_thread_t *) ap_thread_current(void)
-{
-#if AP_HAS_THREAD_LOCAL
-    return current_thread;
-#else
-    return NULL;
-#endif
-}
-
-#endif /* APR_VERSION_AT_LEAST(1,8,0) && !defined(AP_NO_THREAD_LOCAL) */
-
 static apr_status_t main_thread_cleanup(void *arg)
 {
     apr_thread_t *thd = arg;
@@ -3405,11 +3346,79 @@
         return rv;
     }
 
+#if APR_VERSION_AT_LEAST(1,8,0)
+    /* Don't let the thread's pool allocator with no limits */
+    {
+        apr_pool_t *tp = apr_thread_pool_get(*thread);
+        apr_allocator_max_free_set(apr_pool_allocator_get(tp),
+                                   ap_max_mem_free);
+    }
+#endif
+
     apr_pool_cleanup_register(pool, *thread, main_thread_cleanup,
                               apr_pool_cleanup_null);
     return APR_SUCCESS;
 }
 
+#if !APR_VERSION_AT_LEAST(1,8,0)
+
+AP_DECLARE(apr_status_t) ap_thread_current_create(apr_thread_t **current,
+                                                  apr_threadattr_t *attr,
+                                                  apr_pool_t *pool)
+{
+#if AP_HAS_THREAD_LOCAL
+    apr_status_t rv;
+    apr_abortfunc_t abort_fn;
+    apr_os_thread_t osthd;
+    apr_pool_t *p;
+
+    *current = ap_thread_current();
+    if (*current) {
+        return APR_EEXIST;
+    }
+
+    abort_fn = (pool) ? apr_pool_abort_get(pool) : NULL;
+    rv = apr_pool_create_unmanaged_ex(&p, abort_fn, NULL);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+
+    /* Don't let the thread's pool allocator with no limits */
+    apr_allocator_max_free_set(apr_pool_allocator_get(p),
+                               ap_max_mem_free);
+
+    osthd = apr_os_thread_current();
+    rv = apr_os_thread_put(current, &osthd, p);
+    if (rv != APR_SUCCESS) {
+        apr_pool_destroy(p);
+        return rv;
+    }
+
+    current_thread = *current;
+    return APR_SUCCESS;
+#else
+    return APR_ENOTIMPL;
+#endif
+}
+
+AP_DECLARE(void) ap_thread_current_after_fork(void)
+{
+#if AP_HAS_THREAD_LOCAL
+    current_thread = NULL;
+#endif
+}
+
+AP_DECLARE(apr_thread_t *) ap_thread_current(void)
+{
+#if AP_HAS_THREAD_LOCAL
+    return current_thread;
+#else
+    return NULL;
+#endif
+}
+
+#endif /* !APR_VERSION_AT_LEAST(1,8,0) */
+
 #endif /* APR_HAS_THREADS */
 
 AP_DECLARE(void) ap_get_sload(ap_sload_t *ld)