Hi, I got a bug report on the Japanese PHP user's list that states free() aborts within the timer signal handler due to reentrance to the function when max_execution_time takes effect and the signal occurs within the same libc function. The reporter also states he uses apache2handler, which doesn't provide block_interruptions nor unblock_interruptions SAPI handlers in contrast to the apache1 handler.
Whilst I doubt this happens quite frequently because PHP has its own memory pool and it's far more rare that the libc's allocators get called than the emalloc() and efree(), this should be addressed somehow. A proposed fix is attached but note this greatly compromises overall performance due to excessive system calls. Regards, Moriyoshi
Index: sapi/apache2handler/php_apache.h =================================================================== RCS file: /repository/php-src/sapi/apache2handler/php_apache.h,v retrieving revision 1.8.2.1.2.4 diff -u -r1.8.2.1.2.4 php_apache.h --- sapi/apache2handler/php_apache.h 31 Dec 2008 11:17:48 -0000 1.8.2.1.2.4 +++ sapi/apache2handler/php_apache.h 15 Mar 2009 21:13:26 -0000 @@ -46,6 +46,8 @@ int request_processed; /* final content type */ char *content_type; + volatile apr_uint32_t block_sigs_in_cs; + sigset_t old_sig_set; } php_struct; void *merge_php_config(apr_pool_t *p, void *base_conf, void *new_conf); Index: sapi/apache2handler/sapi_apache2.c =================================================================== RCS file: /repository/php-src/sapi/apache2handler/sapi_apache2.c,v retrieving revision 1.57.2.10.2.19 diff -u -r1.57.2.10.2.19 sapi_apache2.c --- sapi/apache2handler/sapi_apache2.c 31 Dec 2008 11:17:48 -0000 1.57.2.10.2.19 +++ sapi/apache2handler/sapi_apache2.c 15 Mar 2009 21:13:27 -0000 @@ -50,6 +50,7 @@ #include "util_script.h" #include "http_core.h" #include "ap_mpm.h" +#include "apr_atomic.h" #include "php_apache.h" @@ -316,6 +317,42 @@ return SUCCESS; } +static void php_apache2_block_signals() +{ +#ifndef PHP_WIN32 + sigset_t ss; + php_struct *ctx = SG(server_context); + + if (!ctx || apr_atomic_cas32(&ctx->block_sigs_in_cs, 1, 0)) { + return; + } + + sigemptyset(&ss); + sigaddset(&ss, SIGPROF); + sigaddset(&ss, SIGALRM); +#if defined(ZTS) && defined(PTHREADS) + pthread_sigmask(SIG_BLOCK, &ss, &ctx->old_sig_set); +#else + sigprocmask(SIG_BLOCK, &ss, &ctx->old_sig_set); +#endif +#endif +} + +static void php_apache2_unblock_signals() +{ +#ifndef PHP_WIN32 + php_struct *ctx = SG(server_context); + if (!ctx || !apr_atomic_cas32(&ctx->block_sigs_in_cs, 0, 1)) { + return; + } +#if defined(ZTS) && defined(PTHREADS) + pthread_sigmask(SIG_SETMASK, &ctx->old_sig_set, NULL); +#else + sigprocmask(SIG_SETMASK, &ctx->old_sig_set, NULL); +#endif +#endif +} + static sapi_module_struct apache2_sapi_module = { "apache2handler", "Apache 2.0 Handler", @@ -344,7 +381,10 @@ php_apache_sapi_log_message, /* Log message */ php_apache_sapi_get_request_time, /* Request Time */ - STANDARD_SAPI_MODULE_PROPERTIES + NULL, /* php.ini path override */ + + php_apache2_block_signals, + php_apache2_unblock_signals }; static apr_status_t php_apache_server_shutdown(void *tmp) @@ -523,6 +563,8 @@ */ apr_pool_cleanup_register(r->pool, (void *)&SG(server_context), php_server_context_cleanup, apr_pool_cleanup_null); ctx->r = r; + ctx->block_sigs_in_cs = 0; + sigemptyset(&ctx->old_sig_set); ctx = NULL; /* May look weird to null it here, but it is to catch the right case in the first_try later on */ } else { parent_req = ctx->r;
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php