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)