From 770cb1da71656fa0dce7dfab26e5e88cb557b639 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 22 Apr 2015 02:29:06 +0300 Subject: [PATCH] Keep realpath and PCRE caches in consistency with opcache SHM. --- Zend/zend_hash.c | 7 +++++ Zend/zend_hash.h | 1 + ext/opcache/ZendAccelerator.c | 48 ++++++++++++++++++++++++++++++++++- ext/opcache/ZendAccelerator.h | 1 + ext/pcre/php_pcre.c | 11 ++++++-- ext/pcre/php_pcre.h | 2 ++ 6 files changed, 67 insertions(+), 3 deletions(-) diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index fcb51f6a2f..5aa8620683 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -924,6 +924,13 @@ static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint32_t idx, Bu _zend_hash_del_el_ex(ht, idx, p, prev); } +ZEND_API void ZEND_FASTCALL zend_hash_del_bucket(HashTable *ht, Bucket *p) +{ + IS_CONSISTENT(ht); + HT_ASSERT(GC_REFCOUNT(ht) == 1); + _zend_hash_del_el(ht, HT_IDX_TO_HASH(p - ht->arData), p); +} + ZEND_API int ZEND_FASTCALL zend_hash_del(HashTable *ht, zend_string *key) { zend_ulong h; diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 9dec40d57a..7ef9242ad2 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -145,6 +145,7 @@ ZEND_API int ZEND_FASTCALL zend_hash_del_ind(HashTable *ht, zend_string *key); ZEND_API int ZEND_FASTCALL zend_hash_str_del(HashTable *ht, const char *key, size_t len); ZEND_API int ZEND_FASTCALL zend_hash_str_del_ind(HashTable *ht, const char *key, size_t len); ZEND_API int ZEND_FASTCALL zend_hash_index_del(HashTable *ht, zend_ulong h); +ZEND_API void ZEND_FASTCALL zend_hash_del_bucket(HashTable *ht, Bucket *p); /* Data retreival */ ZEND_API zval* ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key); diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 8259cfa9af..ede6efd94c 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -39,6 +39,7 @@ #include "zend_virtual_cwd.h" #include "zend_accelerator_util_funcs.h" #include "zend_accelerator_hash.h" +#include "ext/pcre/php_pcre.h" #ifndef ZEND_WIN32 #include @@ -1799,8 +1800,26 @@ static void zend_reset_cache_vars(void) ZCSG(force_restart_time) = 0; } +#ifndef ZTS +static void accel_reset_pcre_cache(void) +{ + Bucket *p; + + ZEND_HASH_FOREACH_BUCKET(&PCRE_G(pcre_cache), p) { + /* Remove PCRE cache entries with inconsistent keys */ + if (IS_ACCEL_INTERNED(p->key)) { + p->key = NULL; + zend_hash_del_bucket(&PCRE_G(pcre_cache), p); + } + } ZEND_HASH_FOREACH_END(); +} +#endif + static void accel_activate(void) { +#ifndef ZTS + zend_bool reset_pcre = 0; +#endif if (!ZCG(enabled) || !accel_startup_ok) { return; @@ -1860,9 +1879,17 @@ static void accel_activate(void) zend_shared_alloc_restore_state(); ZCSG(accelerator_enabled) = ZCSG(cache_status_before_restart); - ZCSG(last_restart_time) = ZCG(request_time); + if (ZCSG(last_restart_time) < ZCG(request_time)) { + ZCSG(last_restart_time) = ZCG(request_time); + } else { + ZCSG(last_restart_time)++; + } accel_restart_leave(); } +#ifndef ZTS + } else { + reset_pcre = 1; +#endif } zend_shared_alloc_unlock(); } @@ -1877,6 +1904,20 @@ static void accel_activate(void) ZCG(cwd_check) = 1; SHM_PROTECT(); + + if (ZCSG(last_restart_time) != ZCG(last_restart_time)) { + /* SHM was reinitialized. */ + ZCG(last_restart_time) = ZCSG(last_restart_time); + + /* Reset in-process realpath cache */ + realpath_cache_clean(); + +#ifndef ZTS + accel_reset_pcre_cache(); + } else if (reset_pcre) { + accel_reset_pcre_cache(); +#endif + } } #if !ZEND_DEBUG @@ -2316,6 +2357,9 @@ static int accel_startup(zend_extension *extension) break; } + /* remeber the last restart time in the process memory */ + ZCG(last_restart_time) = ZCSG(last_restart_time); + /* from this point further, shared memory is supposed to be OK */ /* Init auto-global strings */ @@ -2400,6 +2444,8 @@ void accel_shutdown(void) zend_hash_clean(CG(function_table)); zend_hash_clean(CG(class_table)); zend_hash_clean(EG(zend_constants)); + + accel_reset_pcre_cache(); #endif } diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index aa38562687..a41d0a94d0 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -237,6 +237,7 @@ typedef struct _zend_accel_globals { int cwd_check; int auto_globals_mask; time_t request_time; + time_t last_restart_time; /* used to synchronize SHM and in-process caches */ /* preallocated shared-memory block to save current script */ void *mem; void *arena_mem; diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 4c29905d2f..1f013408fc 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -54,7 +54,7 @@ enum { }; -ZEND_DECLARE_MODULE_GLOBALS(pcre) +PHPAPI ZEND_DECLARE_MODULE_GLOBALS(pcre) static void pcre_handle_exec_error(int pcre_code) /* {{{ */ @@ -482,7 +482,14 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex) * as hash keys especually for this table. * See bug #63180 */ - pce = zend_hash_str_update_mem(&PCRE_G(pcre_cache), regex->val, regex->len, &new_entry, sizeof(pcre_cache_entry)); + if (!IS_INTERNED(regex) || !(GC_FLAGS(regex) & IS_STR_PERMANENT)) { + zend_string *str = zend_string_init(regex->val, regex->len, 1); + GC_REFCOUNT(str) = 0; /* will be incremented by zend_hash_update_mem() */ + str->h = regex->h; + regex = str; + } + + pce = zend_hash_update_mem(&PCRE_G(pcre_cache), regex, &new_entry, sizeof(pcre_cache_entry)); return pce; } diff --git a/ext/pcre/php_pcre.h b/ext/pcre/php_pcre.h index 98882cce4e..fb155c467e 100644 --- a/ext/pcre/php_pcre.h +++ b/ext/pcre/php_pcre.h @@ -81,6 +81,8 @@ ZEND_BEGIN_MODULE_GLOBALS(pcre) int error_code; ZEND_END_MODULE_GLOBALS(pcre) +PHPAPI ZEND_EXTERN_MODULE_GLOBALS(pcre); + #ifdef ZTS # define PCRE_G(v) ZEND_TSRMG(pcre_globals_id, zend_pcre_globals *, v) #else -- 2.40.0