From: Yann Ylavic Date: Fri, 15 Jul 2022 09:24:01 +0000 (+0000) Subject: core: Apply ap_max_mem_free to created threads' pool allocator. X-Git-Tag: 2.5.0-alpha2-ci-test-only~262 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5382f96a3a0708c050ece38cf70ad8d6808b882c;p=thirdparty%2Fapache%2Fhttpd.git 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 a4c32535c79..1ef00212f4e 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -2571,27 +2571,35 @@ AP_DECLARE(void *) ap_realloc(void *ptr, size_t size) #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 @@ AP_DECLARE(void *) ap_realloc(void *ptr, size_t size) #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,16 +2620,15 @@ AP_DECLARE(apr_status_t) ap_thread_current_create(apr_thread_t **current, 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); +#endif /* APR_VERSION_AT_LEAST(1,8,0) */ -#else /* APR_HAS_THREADS */ +#endif /* APR_HAS_THREADS */ +#ifdef AP_THREAD_LOCAL +#define AP_HAS_THREAD_LOCAL 1 +#else #define AP_HAS_THREAD_LOCAL 0 - -#endif /* APR_HAS_THREADS */ +#endif /** * Get server load params diff --git a/server/util.c b/server/util.c index cc0adbccd8e..63c5132f2c9 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 @@ AP_DECLARE(void *) ap_realloc(void *ptr, size_t size) #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,15 +3322,53 @@ AP_DECLARE(apr_status_t) ap_thread_create(apr_thread_t **thread, return apr_thread_create(thread, attr, thread_start, ctx, pool); } -#endif /* AP_HAS_THREAD_LOCAL */ +static apr_status_t main_thread_cleanup(void *arg) +{ + apr_thread_t *thd = arg; + apr_pool_destroy(apr_thread_pool_get(thd)); + return APR_SUCCESS; +} + +AP_DECLARE(apr_status_t) ap_thread_main_create(apr_thread_t **thread, + apr_pool_t *pool) +{ + apr_status_t rv; + apr_threadattr_t *attr = NULL; + + /* Create an apr_thread_t for the main child thread to set up its Thread + * Local Storage. Since it's detached and won't apr_thread_exit(), destroy + * its pool before exiting via a cleanup of the given pool. + */ + if ((rv = apr_threadattr_create(&attr, pool)) + || (rv = apr_threadattr_detach_set(attr, 1)) + || (rv = ap_thread_current_create(thread, attr, pool))) { + *thread = NULL; + 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_pool_abort_get(pool); - apr_allocator_t *allocator; + apr_abortfunc_t abort_fn; apr_os_thread_t osthd; apr_pool_t *p; @@ -3337,18 +3377,15 @@ AP_DECLARE(apr_status_t) ap_thread_current_create(apr_thread_t **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); + abort_fn = (pool) ? apr_pool_abort_get(pool) : NULL; + rv = apr_pool_create_unmanaged_ex(&p, abort_fn, NULL); if (rv != APR_SUCCESS) { - apr_allocator_destroy(allocator); return rv; } - apr_allocator_owner_set(allocator, p); + + /* 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); @@ -3357,10 +3394,11 @@ AP_DECLARE(apr_status_t) ap_thread_current_create(apr_thread_t **current, return rv; } -#if AP_HAS_THREAD_LOCAL current_thread = *current; -#endif return APR_SUCCESS; +#else + return APR_ENOTIMPL; +#endif } AP_DECLARE(void) ap_thread_current_after_fork(void) @@ -3379,36 +3417,7 @@ AP_DECLARE(apr_thread_t *) ap_thread_current(void) #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; - apr_pool_destroy(apr_thread_pool_get(thd)); - return APR_SUCCESS; -} - -AP_DECLARE(apr_status_t) ap_thread_main_create(apr_thread_t **thread, - apr_pool_t *pool) -{ - apr_status_t rv; - apr_threadattr_t *attr = NULL; - - /* Create an apr_thread_t for the main child thread to set up its Thread - * Local Storage. Since it's detached and won't apr_thread_exit(), destroy - * its pool before exiting via a cleanup of the given pool. - */ - if ((rv = apr_threadattr_create(&attr, pool)) - || (rv = apr_threadattr_detach_set(attr, 1)) - || (rv = ap_thread_current_create(thread, attr, pool))) { - *thread = NULL; - return rv; - } - - apr_pool_cleanup_register(pool, *thread, main_thread_cleanup, - apr_pool_cleanup_null); - return APR_SUCCESS; -} +#endif /* !APR_VERSION_AT_LEAST(1,8,0) */ #endif /* APR_HAS_THREADS */