From 6084765a252cdbe4fe24ef5a78e080b4ce5753d3 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Wed, 5 Jul 2023 13:27:44 +0200 Subject: [PATCH 01/27] Add ZendMM observer --- Zend/zend_alloc.c | 269 +++++++++++++++++++++++++++++++++++++++++++--- Zend/zend_alloc.h | 29 ++++- main/main.c | 6 ++ 3 files changed, 284 insertions(+), 20 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 942a8b8e1309..e717bf3943fb 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -50,6 +50,7 @@ * with more specialized routines when the requested size is known. */ +#include "php.h" #include "zend.h" #include "zend_alloc.h" #include "zend_globals.h" @@ -230,6 +231,37 @@ typedef struct _zend_mm_huge_list zend_mm_huge_list; static bool zend_mm_use_huge_pages = false; +struct _zend_mm_observer { + void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void (*gc)(size_t len); + void (*shutdown)(bool full, bool silent); + zend_mm_observer *next; +}; + +#define HANDLE_NO_DEBUG_OBSERVERS(observer_function, ...) \ + if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { \ + zend_mm_observer *current = heap->observers; \ + while (current != NULL) { \ + if (current->observer_function != NULL) { \ + current->observer_function(__VA_ARGS__); \ + } \ + current = current->next; \ + } \ + } + +#define HANDLE_OBSERVERS(observer_function, ...) \ + if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { \ + zend_mm_observer *current = heap->observers; \ + while (current != NULL) { \ + if (current->observer_function != NULL) { \ + current->observer_function(__VA_ARGS__ ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ + } \ + current = current->next; \ + } \ + } + /* * Memory is retrieved from OS by chunks of fixed size 2MB. * Inside chunk it's managed by pages of fixed size 4096B. @@ -262,9 +294,25 @@ static bool zend_mm_use_huge_pages = false; * 2 for 5-8, 3 for 9-16 etc) see zend_alloc_sizes.h */ + +struct _zend_mm_observer { + void (*malloc)(size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void (*free)(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void (*realloc)(void *, size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + zend_mm_observer *next; +}; +zend_mm_observer *zend_mm_observers = NULL; + +typedef struct _zend_mm_heap_observer zend_mm_heap_observer; +struct _zend_mm_heap_observer { + zend_mm_observer *observer; + bool enabled; + zend_mm_heap_observer *next; +}; + struct _zend_mm_heap { #if ZEND_MM_CUSTOM - int use_custom_heap; + int use_custom_heap; /* bitflag */ #endif #if ZEND_MM_STORAGE zend_mm_storage *storage; @@ -315,6 +363,7 @@ struct _zend_mm_heap { bool check_freelists_on_shutdown; } debug; }; + zend_mm_observer *observers; #endif #if ZEND_DEBUG pid_t pid; @@ -2085,6 +2134,8 @@ static zend_mm_heap *zend_mm_init(void) #endif #if ZEND_MM_CUSTOM heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_NONE; + heap->observers = NULL; + zend_mm_observers_startup(heap); #endif #if ZEND_MM_STORAGE heap->storage = NULL; @@ -2108,13 +2159,14 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap) size_t collected = 0; #if ZEND_MM_CUSTOM - if (heap->use_custom_heap) { + if (heap->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { size_t (*gc)(void) = heap->custom_heap._gc; if (gc) { return gc(); } return 0; } + HANDLE_NO_DEBUG_OBSERVERS(gc, collected) #endif for (i = 0; i < ZEND_MM_BINS; i++) { @@ -2435,7 +2487,7 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) zend_mm_huge_list *list; #if ZEND_MM_CUSTOM - if (heap->use_custom_heap) { + if (heap->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { if (heap->custom_heap._malloc == tracked_malloc) { if (silent) { tracked_free_all(heap); @@ -2463,6 +2515,8 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) shutdown(full, silent); } + HANDLE_NO_DEBUG_OBSERVERS(shutdown, full, silent) + return; } #endif @@ -2623,7 +2677,7 @@ static zend_alloc_globals alloc_globals; ZEND_API bool is_zend_mm(void) { #if ZEND_MM_CUSTOM - return !AG(mm_heap)->use_custom_heap; + return !(AG(mm_heap)->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED); #else return true; #endif @@ -2632,7 +2686,7 @@ ZEND_API bool is_zend_mm(void) ZEND_API bool is_zend_ptr(const void *ptr) { #if ZEND_MM_CUSTOM - if (AG(mm_heap)->use_custom_heap) { + if (AG(mm_heap)->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { if (AG(mm_heap)->custom_heap._malloc == tracked_malloc) { zend_ulong h = ((uintptr_t) ptr) >> ZEND_MM_ALIGNMENT_LOG2; zval *size_zv = zend_hash_index_find(AG(mm_heap)->tracked_allocs, h); @@ -2664,7 +2718,6 @@ ZEND_API bool is_zend_ptr(const void *ptr) } block = block->next; } - return 0; } @@ -2774,8 +2827,24 @@ ZEND_API void ZEND_FASTCALL _efree_huge(void *ptr, size_t size) ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { #if ZEND_MM_CUSTOM - if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { - return AG(mm_heap)->custom_heap._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ + zend_mm_heap *heap = AG(mm_heap); + int use_custom_heap = heap->use_custom_heap; + + if (UNEXPECTED(use_custom_heap)) { + void *ptr; + + // Check for actual custom handler (excluding observer bit) + if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { + ptr = heap->custom_heap._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } else { + // No custom handler, use default heap + ptr = zend_mm_alloc_heap(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + + // Call observers if present + HANDLE_OBSERVERS(malloc, size, ptr) + + return ptr; } #endif return zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); @@ -2784,8 +2853,20 @@ ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LI ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { #if ZEND_MM_CUSTOM - if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { - AG(mm_heap)->custom_heap._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + zend_mm_heap *heap = AG(mm_heap); + int use_custom_heap = heap->use_custom_heap; + + if (UNEXPECTED(use_custom_heap)) { + // Call observers first (before free) + HANDLE_OBSERVERS(free, ptr) + + // Check for actual custom handler (excluding observer bit) + if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { + heap->custom_heap._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } else { + // No custom handler, use default heap + zend_mm_free_heap(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } return; } #endif @@ -2795,8 +2876,24 @@ ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_OR ZEND_API void* ZEND_FASTCALL _erealloc(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { #if ZEND_MM_CUSTOM - if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { - return AG(mm_heap)->custom_heap._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + zend_mm_heap *heap = AG(mm_heap); + int use_custom_heap = heap->use_custom_heap; + + if (UNEXPECTED(use_custom_heap)) { + void *new_ptr; + + // Check for actual custom handler (excluding observer bit) + if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { + new_ptr = heap->custom_heap._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } else { + // No custom handler, use default heap + new_ptr = zend_mm_realloc_heap(heap, ptr, size, 0, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + + // Call observers if present + HANDLE_OBSERVERS(realloc, ptr, size, new_ptr) + + return new_ptr; } #endif return zend_mm_realloc_heap(AG(mm_heap), ptr, size, 0, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); @@ -2805,8 +2902,24 @@ ZEND_API void* ZEND_FASTCALL _erealloc(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_API void* ZEND_FASTCALL _erealloc2(void *ptr, size_t size, size_t copy_size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { #if ZEND_MM_CUSTOM - if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { - return AG(mm_heap)->custom_heap._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + zend_mm_heap *heap = AG(mm_heap); + int use_custom_heap = heap->use_custom_heap; + + if (UNEXPECTED(use_custom_heap)) { + void *new_ptr; + + // Check for actual custom handler (excluding observer bit) + if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { + new_ptr = heap->custom_heap._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } else { + // No custom handler, use default heap + new_ptr = zend_mm_realloc_heap(heap, ptr, size, 1, copy_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + + // Call observers if present + HANDLE_OBSERVERS(realloc, ptr, size, new_ptr) + + return new_ptr; } #endif return zend_mm_realloc_heap(AG(mm_heap), ptr, size, 1, copy_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); @@ -3299,6 +3412,7 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals) mm_heap->tracked_allocs = malloc(sizeof(HashTable)); zend_hash_init(mm_heap->tracked_allocs, 1024, NULL, NULL, 1); } + zend_mm_observers_startup(mm_heap); return; } #endif @@ -3321,6 +3435,7 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals) #ifdef ZTS static void alloc_globals_dtor(zend_alloc_globals *alloc_globals) { + zend_mm_observers_shutdown(alloc_globals->mm_heap); zend_mm_shutdown(alloc_globals->mm_heap, 1, 1); } #endif @@ -3358,9 +3473,18 @@ ZEND_API zend_mm_heap *zend_mm_get_heap(void) ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap) { #if ZEND_MM_CUSTOM - return AG(mm_heap)->use_custom_heap; + return (AG(mm_heap)->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) != 0; #else - return 0; + return false; +#endif +} + +ZEND_API bool zend_mm_is_observed(zend_mm_heap *new_heap) +{ +#if ZEND_MM_CUSTOM + return (AG(mm_heap)->use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) != 0; +#else + return false; #endif } @@ -3383,6 +3507,7 @@ ZEND_API void zend_mm_set_custom_handlers_ex(zend_mm_heap *heap, { #if ZEND_MM_CUSTOM zend_mm_heap *_heap = (zend_mm_heap*)heap; + int observed = _heap->use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED; if (!_malloc && !_free && !_realloc) { _heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_NONE; @@ -3394,6 +3519,8 @@ ZEND_API void zend_mm_set_custom_handlers_ex(zend_mm_heap *heap, _heap->custom_heap._gc = _gc; _heap->custom_heap._shutdown = _shutdown; } + + _heap->use_custom_heap |= observed; #endif } @@ -3417,7 +3544,7 @@ ZEND_API void zend_mm_get_custom_handlers_ex(zend_mm_heap *heap, #if ZEND_MM_CUSTOM zend_mm_heap *_heap = (zend_mm_heap*)heap; - if (heap->use_custom_heap) { + if (heap->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { *_malloc = _heap->custom_heap._malloc; *_free = _heap->custom_heap._free; *_realloc = _heap->custom_heap._realloc; @@ -3447,6 +3574,114 @@ ZEND_API void zend_mm_get_custom_handlers_ex(zend_mm_heap *heap, #endif } +ZEND_API zend_mm_observer* zend_mm_observer_register( + zend_mm_heap *heap, + void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*gc)(size_t len), + void (*shutdown)(bool full, bool silent) +) { +#if ZEND_MM_CUSTOM + if (heap == NULL) { + heap = AG(mm_heap); + } + + zend_mm_observer *node = pemalloc(sizeof(zend_mm_observer), 1); + node->malloc = malloc; + node->free = free; + node->realloc = realloc; + node->gc = gc; + node->shutdown = shutdown; + node->next = NULL; + + if (heap->observers == NULL) { + heap->observers = node; + } else { + zend_mm_observer *current = heap->observers; + while (current->next != NULL) { + current = current->next; + } + current->next = node; + } + + heap->use_custom_heap |= ZEND_MM_CUSTOM_HEAP_OBSERVED; + return node; +#else + return NULL; +#endif +} + +ZEND_API bool zend_mm_is_observed(zend_mm_heap *heap) +{ +#if ZEND_MM_CUSTOM + if (heap == NULL) { + heap = AG(mm_heap); + } + return (heap->use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) != 0; +#else + return false; +#endif +} + +ZEND_API bool zend_mm_observer_unregister(zend_mm_heap *heap, zend_mm_observer *observer) +{ +#if ZEND_MM_CUSTOM + if (heap == NULL) { + heap = AG(mm_heap); + } + if (heap->observers == NULL) { + return false; + } + + zend_mm_observer *prev = NULL; + zend_mm_observer *current = heap->observers; + + while (current != NULL) { + if (current == observer) { + if (prev == NULL) { + heap->observers = current->next; + } else { + prev->next = current->next; + } + pefree(current, 1); + + // Update flag if no more observers + if (heap->observers == NULL) { + heap->use_custom_heap &= ~ZEND_MM_CUSTOM_HEAP_OBSERVED; + } + return true; + } + prev = current; + current = current->next; + } +#endif + return false; +} + +void zend_mm_observers_shutdown(zend_mm_heap *heap) +{ +#if ZEND_MM_CUSTOM + if (heap == NULL) { + heap = AG(mm_heap); + if (heap == NULL) { + return; + } + } + + zend_mm_observer *current = heap->observers; + zend_mm_observer *next = NULL; + + while (current != NULL) { + next = current->next; + pefree(current, 1); + current = next; + } + + heap->observers = NULL; + heap->use_custom_heap &= ~ZEND_MM_CUSTOM_HEAP_OBSERVED; +#endif +} ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap) { #if ZEND_MM_STORAGE diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index ff51c4fe8652..d90ec4c89cf5 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -268,9 +268,10 @@ ZEND_API zend_mm_heap *zend_mm_get_heap(void); ZEND_API size_t zend_mm_gc(zend_mm_heap *heap); -#define ZEND_MM_CUSTOM_HEAP_NONE 0 -#define ZEND_MM_CUSTOM_HEAP_STD 1 -#define ZEND_MM_CUSTOM_HEAP_DEBUG 2 +#define ZEND_MM_CUSTOM_HEAP_NONE 0 +#define ZEND_MM_CUSTOM_HEAP_STD 1 +#define ZEND_MM_CUSTOM_HEAP_DEBUG 2 +#define ZEND_MM_CUSTOM_HEAP_OBSERVED 4 ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap); ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, @@ -294,6 +295,28 @@ ZEND_API void zend_mm_get_custom_handlers_ex(zend_mm_heap *heap, size_t (**_gc)(void), void (**_shutdown)(bool, bool)); +typedef struct _zend_mm_observer zend_mm_observer; + +// thread local +ZEND_API bool zend_mm_is_observed(zend_mm_heap *heap); +ZEND_API zend_mm_observer* zend_mm_observer_register( + zend_mm_heap *heap, + void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*gc)(size_t len), + void (*shutdown)(bool full, bool silent) +); +ZEND_API bool zend_mm_observer_unregister(zend_mm_heap *heap, zend_mm_observer *observer); +void zend_mm_observers_shutdown(zend_mm_heap *heap); + +#if ZEND_DEBUG +ZEND_API void zend_mm_set_custom_debug_handlers(zend_mm_heap *heap, + void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)); +#endif + typedef struct _zend_mm_storage zend_mm_storage; typedef void* (*zend_mm_chunk_alloc_t)(zend_mm_storage *storage, size_t size, size_t alignment); diff --git a/main/main.c b/main/main.c index cc3f1cae2586..a7298e77274d 100644 --- a/main/main.c +++ b/main/main.c @@ -2357,6 +2357,8 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi php_ini_register_extensions(); zend_startup_modules(); + zend_mm_observers_startup(NULL); + /* start Zend extensions */ zend_startup_extensions(); @@ -2502,6 +2504,10 @@ void php_module_shutdown(void) return; } + // we need to shutdown ZendMM observers before modules are unloaded + zend_mm_observers_shutdown(NULL); + zend_mm_observers_unregister(); + zend_interned_strings_switch_storage(0); #if ZEND_RC_DEBUG From c9cd71624657e822878e920dd8884b78bef2dc8e Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Mon, 24 Jul 2023 08:57:33 +0200 Subject: [PATCH 02/27] remove `php.h` --- Zend/zend_alloc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index e717bf3943fb..5e8ef11eafe6 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -50,7 +50,6 @@ * with more specialized routines when the requested size is known. */ -#include "php.h" #include "zend.h" #include "zend_alloc.h" #include "zend_globals.h" From 5c4e6a194f2fe7216ee7284acfe885872f390475 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Mon, 24 Jul 2023 09:16:50 +0200 Subject: [PATCH 03/27] Add missing `ZEND_API` --- Zend/zend_alloc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 5e8ef11eafe6..e717bf3943fb 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -50,6 +50,7 @@ * with more specialized routines when the requested size is known. */ +#include "php.h" #include "zend.h" #include "zend_alloc.h" #include "zend_globals.h" From f5d57011c2dee0350064dfa0ab18af3cbe6f7c6a Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Tue, 25 Jul 2023 12:27:29 +0200 Subject: [PATCH 04/27] make observer less complex --- main/main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/main/main.c b/main/main.c index a7298e77274d..b85a41ecbd51 100644 --- a/main/main.c +++ b/main/main.c @@ -2357,8 +2357,6 @@ zend_result php_module_startup(sapi_module_struct *sf, zend_module_entry *additi php_ini_register_extensions(); zend_startup_modules(); - zend_mm_observers_startup(NULL); - /* start Zend extensions */ zend_startup_extensions(); @@ -2506,7 +2504,6 @@ void php_module_shutdown(void) // we need to shutdown ZendMM observers before modules are unloaded zend_mm_observers_shutdown(NULL); - zend_mm_observers_unregister(); zend_interned_strings_switch_storage(0); From f0e3900643667f129dbd6cd12fe2abeef0e78409 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Tue, 25 Jul 2023 21:28:41 +0200 Subject: [PATCH 05/27] shutdown ZendMM observers during request shutdown --- Zend/zend_alloc.c | 4 ++++ main/main.c | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index e717bf3943fb..138009eb1382 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2486,6 +2486,10 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) zend_mm_chunk *p; zend_mm_huge_list *list; + if (full == false) { + zend_mm_observers_shutdown(heap); + } + #if ZEND_MM_CUSTOM if (heap->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { if (heap->custom_heap._malloc == tracked_malloc) { diff --git a/main/main.c b/main/main.c index b85a41ecbd51..cc3f1cae2586 100644 --- a/main/main.c +++ b/main/main.c @@ -2502,9 +2502,6 @@ void php_module_shutdown(void) return; } - // we need to shutdown ZendMM observers before modules are unloaded - zend_mm_observers_shutdown(NULL); - zend_interned_strings_switch_storage(0); #if ZEND_RC_DEBUG From 252fd60d84fa5b0314cb9ec04dcf3d16fff969a2 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Wed, 26 Jul 2023 12:53:16 +0200 Subject: [PATCH 06/27] add tests for ZendMM Observer --- ext/zend_test/config.m4 | 1 + ext/zend_test/config.w32 | 3 +- ext/zend_test/php_test.h | 3 + ext/zend_test/test.c | 4 + .../tests/zendmm_observer_all_01.phpt | 16 +++ .../tests/zendmm_observer_part_01.phpt | 24 ++++ ext/zend_test/zendmm_observer.c | 117 ++++++++++++++++++ ext/zend_test/zendmm_observer.h | 24 ++++ ext/zend_test/zendmm_observer.stub.php | 9 ++ ext/zend_test/zendmm_observer_arginfo.h | 18 +++ 10 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 ext/zend_test/tests/zendmm_observer_all_01.phpt create mode 100644 ext/zend_test/tests/zendmm_observer_part_01.phpt create mode 100644 ext/zend_test/zendmm_observer.c create mode 100644 ext/zend_test/zendmm_observer.h create mode 100644 ext/zend_test/zendmm_observer.stub.php create mode 100644 ext/zend_test/zendmm_observer_arginfo.h diff --git a/ext/zend_test/config.m4 b/ext/zend_test/config.m4 index f49221b9fb64..38f5fa65bece 100644 --- a/ext/zend_test/config.m4 +++ b/ext/zend_test/config.m4 @@ -11,6 +11,7 @@ if test "$PHP_ZEND_TEST" != "no"; then observer.c test.c zend_mm_custom_handlers.c + zendmm_observer.c ]), [$ext_shared],, [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1]) diff --git a/ext/zend_test/config.w32 b/ext/zend_test/config.w32 index 1e9ae1545dcb..4b4cf5f1a900 100644 --- a/ext/zend_test/config.w32 +++ b/ext/zend_test/config.w32 @@ -3,5 +3,6 @@ ARG_ENABLE("zend-test", "enable zend_test extension", "no"); if (PHP_ZEND_TEST != "no") { - EXTENSION("zend_test", "test.c observer.c fiber.c iterators.c object_handlers.c zend_mm_custom_handlers.c", PHP_ZEND_TEST_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); + EXTENSION("zend_test", "test.c observer.c fiber.c iterators.c object_handlers.c zend_mm_custom_handlers.c zendmm_observer.c", PHP_ZEND_TEST_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); + ADD_FLAG("CFLAGS_ZEND_TEST", "/D PHP_ZEND_TEST_EXPORTS "); } diff --git a/ext/zend_test/php_test.h b/ext/zend_test/php_test.h index e3cf4b4284ba..f8f4fe94a06c 100644 --- a/ext/zend_test/php_test.h +++ b/ext/zend_test/php_test.h @@ -14,6 +14,7 @@ #define PHP_TEST_H #include "fiber.h" +#include "Zend/zend_alloc.h" extern zend_module_entry zend_test_module_entry; #define phpext_zend_test_ptr &zend_test_module_entry @@ -71,6 +72,8 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test) // this is our heap that we install our custom handlers on and inject into // ZendMM zend_mm_heap* observed_heap; + int zendmm_observer_enabled; + zend_mm_observer *observer; ZEND_END_MODULE_GLOBALS(zend_test) extern ZEND_DECLARE_MODULE_GLOBALS(zend_test) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 96f8db83c116..2975c028bea4 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -23,6 +23,7 @@ #include "ext/standard/info.h" #include "php_test.h" #include "observer.h" +#include "zendmm_observer.h" #include "fiber.h" #include "iterators.h" #include "object_handlers.h" @@ -1602,6 +1603,7 @@ PHP_MINIT_FUNCTION(zend_test) zend_test_observer_init(INIT_FUNC_ARGS_PASSTHRU); zend_test_mm_custom_handlers_minit(INIT_FUNC_ARGS_PASSTHRU); + zend_test_mm_observer_minit(INIT_FUNC_ARGS_PASSTHRU); zend_test_fiber_init(); zend_test_iterators_init(); zend_test_object_handlers_init(); @@ -1632,6 +1634,7 @@ PHP_RINIT_FUNCTION(zend_test) zend_hash_init(ZT_G(global_weakmap), 8, NULL, ZVAL_PTR_DTOR, 0); ZT_G(observer_nesting_depth) = 0; zend_test_mm_custom_handlers_rinit(); + zend_test_mm_observer_rinit(); return SUCCESS; } @@ -1647,6 +1650,7 @@ PHP_RSHUTDOWN_FUNCTION(zend_test) } zend_test_mm_custom_handlers_rshutdown(); + zend_test_mm_observer_rshutdown(); return SUCCESS; } diff --git a/ext/zend_test/tests/zendmm_observer_all_01.phpt b/ext/zend_test/tests/zendmm_observer_all_01.phpt new file mode 100644 index 000000000000..6ac0cdb4d05c --- /dev/null +++ b/ext/zend_test/tests/zendmm_observer_all_01.phpt @@ -0,0 +1,16 @@ +--TEST-- +ZendMM Observer: Observe all +--EXTENSIONS-- +zend_test +--INI-- +zend_test.zendmm_observer.enabled=1 +opcache.enable=0 +--FILE-- + +--EXPECTREGEX-- +.* +ZendMM Observer enabled +.* +.* +ZendMM Observer disabled diff --git a/ext/zend_test/tests/zendmm_observer_part_01.phpt b/ext/zend_test/tests/zendmm_observer_part_01.phpt new file mode 100644 index 000000000000..b5671206bc03 --- /dev/null +++ b/ext/zend_test/tests/zendmm_observer_part_01.phpt @@ -0,0 +1,24 @@ +--TEST-- +ZendMM Observer: Observe all +--EXTENSIONS-- +zend_test +--INI-- +zend_test.zendmm_observer.enabled=0 +opcache.enable=0 +--FILE-- + +--EXPECTF-- +malloc 0x%s of size %d (block: %d) +malloc 0x%s of size %d (block: %d) +freed 0x%s of size %d diff --git a/ext/zend_test/zendmm_observer.c b/ext/zend_test/zendmm_observer.c new file mode 100644 index 000000000000..fa42e91f934c --- /dev/null +++ b/ext/zend_test/zendmm_observer.c @@ -0,0 +1,117 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: | + +----------------------------------------------------------------------+ +*/ + +#include "php.h" +#include "php_test.h" +#include "Zend/zend_alloc.h" +#include "ext/standard/info.h" +#include "ext/standard/php_var.h" +#include "zendmm_observer.h" + +void observer_malloc(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + size_t block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); + printf("malloc %p of size %zu (block: %zu)\n", ptr, len, block_len); +} + +void observer_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + size_t block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); + printf("freed %p of size %zu\n", ptr, block_len); +} + +void observer_realloc(void *ptr, size_t len, void *newptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + size_t block_len = zend_mm_block_size(zend_mm_get_heap(), newptr); + printf("realloc %p of size %zu (block: %zu, former %p)\n", newptr, len, block_len, ptr); +} + +PHP_FUNCTION(memprof_enable) +{ + ZEND_PARSE_PARAMETERS_NONE(); + if (ZT_G(observer)) { + RETURN_FALSE; + } + ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), observer_malloc, observer_free, observer_realloc); + RETURN_TRUE; +} + +PHP_FUNCTION(memprof_disable) +{ + ZEND_PARSE_PARAMETERS_NONE(); + zend_mm_observer_unregister(zend_mm_get_heap(), ZT_G(observer)); + ZT_G(observer) = NULL; + RETURN_TRUE; +} + +static PHP_INI_MH(OnUpdate_zend_test_zendmm_observer_enabled) +{ + int int_value; + if (new_value == NULL) { + return FAILURE; + } + + if (zend_string_equals_literal_ci(new_value, "true")) { + int_value = 1; + } else if (zend_string_equals_literal_ci(new_value, "false")) { + int_value = 0; + } else { + int_value = (int) zend_ini_parse_quantity_warn(new_value, entry->name); + } + + if (int_value == 1) { + if (ZT_G(observer) == NULL) { + ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), observer_malloc, observer_free, observer_realloc); + } + } else { + if (ZT_G(observer) != NULL) { + zend_mm_observer_unregister(zend_mm_get_heap(), ZT_G(observer)); + ZT_G(observer) = NULL; + } + } + return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); +} + +PHP_INI_BEGIN() + STD_PHP_INI_BOOLEAN("zend_test.zendmm_observer.enabled", "0", PHP_INI_ALL, OnUpdate_zend_test_zendmm_observer_enabled, zendmm_observer_enabled, zend_zend_test_globals, zend_test_globals) +PHP_INI_END() + +void zend_test_mm_observer_minit(INIT_FUNC_ARGS) +{ + if (type != MODULE_TEMPORARY) { + REGISTER_INI_ENTRIES(); + } else { + (void)ini_entries; + } +} + +void zend_test_mm_observer_rinit(void) +{ + if (ZT_G(zendmm_observer_enabled)) { + printf("ZendMM Observer enabled\n"); + ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), observer_malloc, observer_free, observer_realloc); + } +} + +void zend_test_mm_observer_rshutdown(void) +{ + if (ZT_G(observer)) { + printf("ZendMM Observer disabled\n"); + zend_mm_observer_unregister(zend_mm_get_heap(), ZT_G(observer)); + } + ZT_G(observer) = NULL; +} + diff --git a/ext/zend_test/zendmm_observer.h b/ext/zend_test/zendmm_observer.h new file mode 100644 index 000000000000..c58a452516b1 --- /dev/null +++ b/ext/zend_test/zendmm_observer.h @@ -0,0 +1,24 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_TEST_MM_OBSERVER_H +#define ZEND_TEST_MM_OBSERVER_H + +void zend_test_mm_observer_minit(INIT_FUNC_ARGS); +void zend_test_mm_observer_rinit(void); +void zend_test_mm_observer_rshutdown(void); + +#endif diff --git a/ext/zend_test/zendmm_observer.stub.php b/ext/zend_test/zendmm_observer.stub.php new file mode 100644 index 000000000000..9d90af1a784b --- /dev/null +++ b/ext/zend_test/zendmm_observer.stub.php @@ -0,0 +1,9 @@ + Date: Fri, 28 Jul 2023 15:12:23 +0200 Subject: [PATCH 07/27] rename zendmm -> zend_mm --- ext/zend_test/config.m4 | 2 +- ext/zend_test/config.w32 | 2 +- ext/zend_test/php_test.h | 2 +- ext/zend_test/test.c | 2 +- ...server_all_01.phpt => zend_mm_observer_all_01.phpt} | 2 +- ...rver_part_01.phpt => zend_mm_observer_part_01.phpt} | 10 +++++----- .../{zendmm_observer.c => zend_mm_observer.c} | 8 ++++---- .../{zendmm_observer.h => zend_mm_observer.h} | 0 ...dmm_observer.stub.php => zend_mm_observer.stub.php} | 0 ...m_observer_arginfo.h => zend_mm_observer_arginfo.h} | 0 10 files changed, 14 insertions(+), 14 deletions(-) rename ext/zend_test/tests/{zendmm_observer_all_01.phpt => zend_mm_observer_all_01.phpt} (82%) rename ext/zend_test/tests/{zendmm_observer_part_01.phpt => zend_mm_observer_part_01.phpt} (58%) rename ext/zend_test/{zendmm_observer.c => zend_mm_observer.c} (91%) rename ext/zend_test/{zendmm_observer.h => zend_mm_observer.h} (100%) rename ext/zend_test/{zendmm_observer.stub.php => zend_mm_observer.stub.php} (100%) rename ext/zend_test/{zendmm_observer_arginfo.h => zend_mm_observer_arginfo.h} (100%) diff --git a/ext/zend_test/config.m4 b/ext/zend_test/config.m4 index 38f5fa65bece..c88fa87877c7 100644 --- a/ext/zend_test/config.m4 +++ b/ext/zend_test/config.m4 @@ -11,7 +11,7 @@ if test "$PHP_ZEND_TEST" != "no"; then observer.c test.c zend_mm_custom_handlers.c - zendmm_observer.c + zend_mm_observer.c ]), [$ext_shared],, [-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1]) diff --git a/ext/zend_test/config.w32 b/ext/zend_test/config.w32 index 4b4cf5f1a900..5835c093a5fc 100644 --- a/ext/zend_test/config.w32 +++ b/ext/zend_test/config.w32 @@ -3,6 +3,6 @@ ARG_ENABLE("zend-test", "enable zend_test extension", "no"); if (PHP_ZEND_TEST != "no") { - EXTENSION("zend_test", "test.c observer.c fiber.c iterators.c object_handlers.c zend_mm_custom_handlers.c zendmm_observer.c", PHP_ZEND_TEST_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); + EXTENSION("zend_test", "test.c observer.c fiber.c iterators.c object_handlers.c zend_mm_custom_handlers.c zend_mm_observer.c", PHP_ZEND_TEST_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); ADD_FLAG("CFLAGS_ZEND_TEST", "/D PHP_ZEND_TEST_EXPORTS "); } diff --git a/ext/zend_test/php_test.h b/ext/zend_test/php_test.h index f8f4fe94a06c..81cd66ee2b24 100644 --- a/ext/zend_test/php_test.h +++ b/ext/zend_test/php_test.h @@ -72,7 +72,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test) // this is our heap that we install our custom handlers on and inject into // ZendMM zend_mm_heap* observed_heap; - int zendmm_observer_enabled; + int zend_mm_observer_enabled; zend_mm_observer *observer; ZEND_END_MODULE_GLOBALS(zend_test) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 2975c028bea4..a74a5be32650 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -23,7 +23,7 @@ #include "ext/standard/info.h" #include "php_test.h" #include "observer.h" -#include "zendmm_observer.h" +#include "zend_mm_observer.h" #include "fiber.h" #include "iterators.h" #include "object_handlers.h" diff --git a/ext/zend_test/tests/zendmm_observer_all_01.phpt b/ext/zend_test/tests/zend_mm_observer_all_01.phpt similarity index 82% rename from ext/zend_test/tests/zendmm_observer_all_01.phpt rename to ext/zend_test/tests/zend_mm_observer_all_01.phpt index 6ac0cdb4d05c..76d5fc61ca1d 100644 --- a/ext/zend_test/tests/zendmm_observer_all_01.phpt +++ b/ext/zend_test/tests/zend_mm_observer_all_01.phpt @@ -3,7 +3,7 @@ ZendMM Observer: Observe all --EXTENSIONS-- zend_test --INI-- -zend_test.zendmm_observer.enabled=1 +zend_test.zend_mm_observer.enabled=1 opcache.enable=0 --FILE-- --EXPECTF-- malloc 0x%s of size %d (block: %d) diff --git a/ext/zend_test/zendmm_observer.c b/ext/zend_test/zend_mm_observer.c similarity index 91% rename from ext/zend_test/zendmm_observer.c rename to ext/zend_test/zend_mm_observer.c index fa42e91f934c..6e8b854dc214 100644 --- a/ext/zend_test/zendmm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -19,7 +19,7 @@ #include "Zend/zend_alloc.h" #include "ext/standard/info.h" #include "ext/standard/php_var.h" -#include "zendmm_observer.h" +#include "zend_mm_observer.h" void observer_malloc(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { @@ -57,7 +57,7 @@ PHP_FUNCTION(memprof_disable) RETURN_TRUE; } -static PHP_INI_MH(OnUpdate_zend_test_zendmm_observer_enabled) +static PHP_INI_MH(OnUpdate_zend_test_zend_mm_observer_enabled) { int int_value; if (new_value == NULL) { @@ -86,7 +86,7 @@ static PHP_INI_MH(OnUpdate_zend_test_zendmm_observer_enabled) } PHP_INI_BEGIN() - STD_PHP_INI_BOOLEAN("zend_test.zendmm_observer.enabled", "0", PHP_INI_ALL, OnUpdate_zend_test_zendmm_observer_enabled, zendmm_observer_enabled, zend_zend_test_globals, zend_test_globals) + STD_PHP_INI_BOOLEAN("zend_test.zend_mm_observer.enabled", "0", PHP_INI_ALL, OnUpdate_zend_test_zend_mm_observer_enabled, zend_mm_observer_enabled, zend_zend_test_globals, zend_test_globals) PHP_INI_END() void zend_test_mm_observer_minit(INIT_FUNC_ARGS) @@ -100,7 +100,7 @@ void zend_test_mm_observer_minit(INIT_FUNC_ARGS) void zend_test_mm_observer_rinit(void) { - if (ZT_G(zendmm_observer_enabled)) { + if (ZT_G(zend_mm_observer_enabled)) { printf("ZendMM Observer enabled\n"); ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), observer_malloc, observer_free, observer_realloc); } diff --git a/ext/zend_test/zendmm_observer.h b/ext/zend_test/zend_mm_observer.h similarity index 100% rename from ext/zend_test/zendmm_observer.h rename to ext/zend_test/zend_mm_observer.h diff --git a/ext/zend_test/zendmm_observer.stub.php b/ext/zend_test/zend_mm_observer.stub.php similarity index 100% rename from ext/zend_test/zendmm_observer.stub.php rename to ext/zend_test/zend_mm_observer.stub.php diff --git a/ext/zend_test/zendmm_observer_arginfo.h b/ext/zend_test/zend_mm_observer_arginfo.h similarity index 100% rename from ext/zend_test/zendmm_observer_arginfo.h rename to ext/zend_test/zend_mm_observer_arginfo.h From 51dd7a403f152318f48fb045c29c27404167ccf7 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Fri, 28 Jul 2023 15:18:19 +0200 Subject: [PATCH 08/27] removed unused functions --- ext/zend_test/zend_mm_observer.c | 18 ------------------ ext/zend_test/zend_mm_observer.stub.php | 9 --------- ext/zend_test/zend_mm_observer_arginfo.h | 18 ------------------ 3 files changed, 45 deletions(-) delete mode 100644 ext/zend_test/zend_mm_observer.stub.php delete mode 100644 ext/zend_test/zend_mm_observer_arginfo.h diff --git a/ext/zend_test/zend_mm_observer.c b/ext/zend_test/zend_mm_observer.c index 6e8b854dc214..d81a7af07971 100644 --- a/ext/zend_test/zend_mm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -39,24 +39,6 @@ void observer_realloc(void *ptr, size_t len, void *newptr ZEND_FILE_LINE_DC ZEND printf("realloc %p of size %zu (block: %zu, former %p)\n", newptr, len, block_len, ptr); } -PHP_FUNCTION(memprof_enable) -{ - ZEND_PARSE_PARAMETERS_NONE(); - if (ZT_G(observer)) { - RETURN_FALSE; - } - ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), observer_malloc, observer_free, observer_realloc); - RETURN_TRUE; -} - -PHP_FUNCTION(memprof_disable) -{ - ZEND_PARSE_PARAMETERS_NONE(); - zend_mm_observer_unregister(zend_mm_get_heap(), ZT_G(observer)); - ZT_G(observer) = NULL; - RETURN_TRUE; -} - static PHP_INI_MH(OnUpdate_zend_test_zend_mm_observer_enabled) { int int_value; diff --git a/ext/zend_test/zend_mm_observer.stub.php b/ext/zend_test/zend_mm_observer.stub.php deleted file mode 100644 index 9d90af1a784b..000000000000 --- a/ext/zend_test/zend_mm_observer.stub.php +++ /dev/null @@ -1,9 +0,0 @@ - Date: Fri, 28 Jul 2023 15:21:14 +0200 Subject: [PATCH 09/27] add missing author --- ext/zend_test/zend_mm_observer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/zend_test/zend_mm_observer.h b/ext/zend_test/zend_mm_observer.h index c58a452516b1..1276d6087121 100644 --- a/ext/zend_test/zend_mm_observer.h +++ b/ext/zend_test/zend_mm_observer.h @@ -10,7 +10,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: | + | Author: Florian Engelhardt | +----------------------------------------------------------------------+ */ From e3bb4dfbca091000dda43d7e75ecc3261a9a848c Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Fri, 28 Jul 2023 15:25:55 +0200 Subject: [PATCH 10/27] fix naming and bool parsing --- ext/zend_test/zend_mm_observer.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/ext/zend_test/zend_mm_observer.c b/ext/zend_test/zend_mm_observer.c index d81a7af07971..5c214ddc7475 100644 --- a/ext/zend_test/zend_mm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -39,20 +39,13 @@ void observer_realloc(void *ptr, size_t len, void *newptr ZEND_FILE_LINE_DC ZEND printf("realloc %p of size %zu (block: %zu, former %p)\n", newptr, len, block_len, ptr); } -static PHP_INI_MH(OnUpdate_zend_test_zend_mm_observer_enabled) +static PHP_INI_MH(OnUpdateZendTestMMObserverEnabled) { - int int_value; if (new_value == NULL) { return FAILURE; } - if (zend_string_equals_literal_ci(new_value, "true")) { - int_value = 1; - } else if (zend_string_equals_literal_ci(new_value, "false")) { - int_value = 0; - } else { - int_value = (int) zend_ini_parse_quantity_warn(new_value, entry->name); - } + int int_value = zend_ini_parse_bool(new_value); if (int_value == 1) { if (ZT_G(observer) == NULL) { @@ -68,7 +61,7 @@ static PHP_INI_MH(OnUpdate_zend_test_zend_mm_observer_enabled) } PHP_INI_BEGIN() - STD_PHP_INI_BOOLEAN("zend_test.zend_mm_observer.enabled", "0", PHP_INI_ALL, OnUpdate_zend_test_zend_mm_observer_enabled, zend_mm_observer_enabled, zend_zend_test_globals, zend_test_globals) + STD_PHP_INI_BOOLEAN("zend_test.zend_mm_observer.enabled", "0", PHP_INI_ALL, OnUpdateZendTestMMObserverEnabled, zend_mm_observer_enabled, zend_zend_test_globals, zend_test_globals) PHP_INI_END() void zend_test_mm_observer_minit(INIT_FUNC_ARGS) From d6d97121c695293d150a84edf86afbe3b0091896 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Fri, 28 Jul 2023 15:32:06 +0200 Subject: [PATCH 11/27] make functions static to avoid name clashes --- ext/zend_test/zend_mm_observer.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/ext/zend_test/zend_mm_observer.c b/ext/zend_test/zend_mm_observer.c index 5c214ddc7475..15c79f9ac9f8 100644 --- a/ext/zend_test/zend_mm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -21,21 +21,30 @@ #include "ext/standard/php_var.h" #include "zend_mm_observer.h" -void observer_malloc(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +static void zend_mm_test_observer_malloc(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { - size_t block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); + size_t block_len = 0; + if (is_zend_ptr(ptr)) { + block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); + } printf("malloc %p of size %zu (block: %zu)\n", ptr, len, block_len); } -void observer_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +static void zend_mm_test_observer_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { - size_t block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); + size_t block_len = 0; + if (is_zend_ptr(ptr)) { + block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); + } printf("freed %p of size %zu\n", ptr, block_len); } -void observer_realloc(void *ptr, size_t len, void *newptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +static void zend_mm_test_observer_realloc(void *ptr, size_t len, void *newptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { - size_t block_len = zend_mm_block_size(zend_mm_get_heap(), newptr); + size_t block_len = 0; + if (is_zend_ptr(ptr)) { + block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); + } printf("realloc %p of size %zu (block: %zu, former %p)\n", newptr, len, block_len, ptr); } @@ -49,7 +58,7 @@ static PHP_INI_MH(OnUpdateZendTestMMObserverEnabled) if (int_value == 1) { if (ZT_G(observer) == NULL) { - ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), observer_malloc, observer_free, observer_realloc); + ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), zend_mm_test_observer_malloc, zend_mm_test_observer_free, zend_mm_test_observer_realloc); } } else { if (ZT_G(observer) != NULL) { @@ -77,7 +86,7 @@ void zend_test_mm_observer_rinit(void) { if (ZT_G(zend_mm_observer_enabled)) { printf("ZendMM Observer enabled\n"); - ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), observer_malloc, observer_free, observer_realloc); + ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), zend_mm_test_observer_malloc, zend_mm_test_observer_free, zend_mm_test_observer_realloc); } } From 95711bf7d934e2e9a6248c72f660ea3b07377040 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Fri, 28 Jul 2023 15:32:37 +0200 Subject: [PATCH 12/27] simplyfy test --- ext/zend_test/tests/zend_mm_observer_all_01.phpt | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/zend_test/tests/zend_mm_observer_all_01.phpt b/ext/zend_test/tests/zend_mm_observer_all_01.phpt index 76d5fc61ca1d..b26eb3d13ca6 100644 --- a/ext/zend_test/tests/zend_mm_observer_all_01.phpt +++ b/ext/zend_test/tests/zend_mm_observer_all_01.phpt @@ -12,5 +12,4 @@ opcache.enable=0 .* ZendMM Observer enabled .* -.* ZendMM Observer disabled From cce50cecd7f3cddae3147f765ed5e27e52709ba9 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Fri, 28 Jul 2023 15:55:36 +0200 Subject: [PATCH 13/27] deduplicate observer calling --- Zend/zend_alloc.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 138009eb1382..f580e198a044 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2725,6 +2725,153 @@ ZEND_API bool is_zend_ptr(const void *ptr) return 0; } +<<<<<<< HEAD +||||||| parent of e5d60ddb2c4 (deduplicate observer calling) +#if ZEND_MM_CUSTOM + +static ZEND_COLD void* ZEND_FASTCALL _malloc_custom(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + void *ptr; + zend_mm_heap *heap = AG(mm_heap); + int use_custom_heap = heap->use_custom_heap; + if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) { + ptr = heap->custom_heap.debug._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } else if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_STD) { + ptr = heap->custom_heap.std._malloc(size); + } else { + // no custom memory manager, only observer present + ptr = zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { + zend_mm_observer *current = heap->observers; + while (current != NULL) { + if (current->malloc != NULL) { + current->malloc(size, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + current = current->next; + } + } + return ptr; +} + +static ZEND_COLD void ZEND_FASTCALL _efree_custom(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + zend_mm_heap *heap = AG(mm_heap); + int use_custom_heap = heap->use_custom_heap; + + if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { + zend_mm_observer *current = heap->observers; + while (current != NULL) { + if (current->free != NULL) { + current->free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + current = current->next; + } + } + + if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) { + heap->custom_heap.debug._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } else if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_STD) { + heap->custom_heap.std._free(ptr); + } else { + // no custom memory manager, only observer present + zend_mm_free_heap(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } +} + +static ZEND_COLD void* ZEND_FASTCALL _realloc_custom(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + void *new_ptr; + zend_mm_heap *heap = AG(mm_heap); + int use_custom_heap = heap->use_custom_heap; + if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) { + new_ptr = heap->custom_heap.debug._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } else if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_STD) { + new_ptr = heap->custom_heap.std._realloc(ptr, size); + } else { + // no custom memory manager, only observer present + new_ptr = zend_mm_realloc_heap(AG(mm_heap), ptr, size, 0, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { + zend_mm_observer *current = heap->observers; + while (current != NULL) { + if (current->realloc != NULL) { + current->realloc(ptr, size, new_ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + current = current->next; + } + } + return new_ptr; +} +#endif + +======= +#if ZEND_MM_CUSTOM + +#define HANDLE_OBSERVERS(observer_function, ...) \ + if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { \ + zend_mm_observer *current = heap->observers; \ + while (current != NULL) { \ + if (current->observer_function != NULL) { \ + current->observer_function(__VA_ARGS__ ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ + } \ + current = current->next; \ + } \ + } + +static ZEND_COLD void* ZEND_FASTCALL _malloc_custom(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + void *ptr; + zend_mm_heap *heap = AG(mm_heap); + int use_custom_heap = heap->use_custom_heap; + if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) { + ptr = heap->custom_heap.debug._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } else if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_STD) { + ptr = heap->custom_heap.std._malloc(size); + } else { + // no custom memory manager, only observer present + ptr = zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + HANDLE_OBSERVERS(malloc, size, ptr) + return ptr; +} + +static ZEND_COLD void ZEND_FASTCALL _efree_custom(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + zend_mm_heap *heap = AG(mm_heap); + int use_custom_heap = heap->use_custom_heap; + + HANDLE_OBSERVERS(free, ptr) + + if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) { + heap->custom_heap.debug._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } else if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_STD) { + heap->custom_heap.std._free(ptr); + } else { + // no custom memory manager, only observer present + zend_mm_free_heap(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } +} + +static ZEND_COLD void* ZEND_FASTCALL _realloc_custom(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + void *new_ptr; + zend_mm_heap *heap = AG(mm_heap); + int use_custom_heap = heap->use_custom_heap; + if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) { + new_ptr = heap->custom_heap.debug._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } else if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_STD) { + new_ptr = heap->custom_heap.std._realloc(ptr, size); + } else { + // no custom memory manager, only observer present + new_ptr = zend_mm_realloc_heap(AG(mm_heap), ptr, size, 0, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + HANDLE_OBSERVERS(realloc, ptr, size, new_ptr) + return new_ptr; +} +#endif + +>>>>>>> e5d60ddb2c4 (deduplicate observer calling) #if !ZEND_DEBUG && defined(HAVE_BUILTIN_CONSTANT_P) #undef _emalloc From f8cc8e2c9da568b9cf805d2d7fb788816ad4adc7 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Mon, 31 Jul 2023 12:55:48 +0200 Subject: [PATCH 14/27] Add parameter names --- Zend/zend_alloc.c | 22 ++++++++++++++++++++++ Zend/zend_alloc.h | 11 +++++++++++ 2 files changed, 33 insertions(+) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index f580e198a044..25c18f48a9a6 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -232,11 +232,21 @@ typedef struct _zend_mm_huge_list zend_mm_huge_list; static bool zend_mm_use_huge_pages = false; struct _zend_mm_observer { +<<<<<<< HEAD void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); void (*gc)(size_t len); void (*shutdown)(bool full, bool silent); +||||||| parent of d96128265e4 (Add parameter names) + void (*malloc)(size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void (*free)(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void (*realloc)(void *, size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); +======= + void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); +>>>>>>> d96128265e4 (Add parameter names) zend_mm_observer *next; }; @@ -3726,12 +3736,24 @@ ZEND_API void zend_mm_get_custom_handlers_ex(zend_mm_heap *heap, } ZEND_API zend_mm_observer* zend_mm_observer_register( +<<<<<<< HEAD zend_mm_heap *heap, void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*gc)(size_t len), void (*shutdown)(bool full, bool silent) +||||||| parent of d96128265e4 (Add parameter names) + zend_mm_heap* heap, + void (*malloc)(size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*free)(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*realloc)(void *, size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +======= + zend_mm_heap* heap, + void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +>>>>>>> d96128265e4 (Add parameter names) ) { #if ZEND_MM_CUSTOM if (heap == NULL) { diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index d90ec4c89cf5..fee8506a31f6 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -301,11 +301,22 @@ typedef struct _zend_mm_observer zend_mm_observer; ZEND_API bool zend_mm_is_observed(zend_mm_heap *heap); ZEND_API zend_mm_observer* zend_mm_observer_register( zend_mm_heap *heap, +<<<<<<< HEAD void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*gc)(size_t len), void (*shutdown)(bool full, bool silent) +||||||| parent of d96128265e4 (Add parameter names) + void (*malloc)(size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*free)(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*realloc)(void *, size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +======= + void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) + +>>>>>>> d96128265e4 (Add parameter names) ); ZEND_API bool zend_mm_observer_unregister(zend_mm_heap *heap, zend_mm_observer *observer); void zend_mm_observers_shutdown(zend_mm_heap *heap); From 3f498b146538d53e2a3098e40c3291858b3766c1 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Mon, 31 Jul 2023 15:20:06 +0200 Subject: [PATCH 15/27] fix test --- .../tests/zend_mm_observer_free_01.phpt | 16 +++++++++++++ .../tests/zend_mm_observer_malloc_01.phpt | 15 ++++++++++++ .../tests/zend_mm_observer_part_01.phpt | 24 ------------------- .../tests/zend_mm_observer_realloc_01.phpt | 24 +++++++++++++++++++ ext/zend_test/zend_mm_observer.c | 3 +++ 5 files changed, 58 insertions(+), 24 deletions(-) create mode 100644 ext/zend_test/tests/zend_mm_observer_free_01.phpt create mode 100644 ext/zend_test/tests/zend_mm_observer_malloc_01.phpt delete mode 100644 ext/zend_test/tests/zend_mm_observer_part_01.phpt create mode 100644 ext/zend_test/tests/zend_mm_observer_realloc_01.phpt diff --git a/ext/zend_test/tests/zend_mm_observer_free_01.phpt b/ext/zend_test/tests/zend_mm_observer_free_01.phpt new file mode 100644 index 000000000000..44747b9694a6 --- /dev/null +++ b/ext/zend_test/tests/zend_mm_observer_free_01.phpt @@ -0,0 +1,16 @@ +--TEST-- +ZendMM Observer: Observe free +--EXTENSIONS-- +zend_test +--INI-- +zend_test.zend_mm_observer.enabled=0 +opcache.enable=0 +--FILE-- + +--EXPECTREGEX-- +.*freed 0x\S+ of size \d+.* diff --git a/ext/zend_test/tests/zend_mm_observer_malloc_01.phpt b/ext/zend_test/tests/zend_mm_observer_malloc_01.phpt new file mode 100644 index 000000000000..ccaeb690fd2e --- /dev/null +++ b/ext/zend_test/tests/zend_mm_observer_malloc_01.phpt @@ -0,0 +1,15 @@ +--TEST-- +ZendMM Observer: Observe malloc +--EXTENSIONS-- +zend_test +--INI-- +zend_test.zend_mm_observer.enabled=0 +opcache.enable=0 +--FILE-- + +--EXPECTREGEX-- +.*malloc 0x\S+ of size \d+ \(block: \d+\).* diff --git a/ext/zend_test/tests/zend_mm_observer_part_01.phpt b/ext/zend_test/tests/zend_mm_observer_part_01.phpt deleted file mode 100644 index 31fbb4fdfcb4..000000000000 --- a/ext/zend_test/tests/zend_mm_observer_part_01.phpt +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -ZendMM Observer: Observe all ---EXTENSIONS-- -zend_test ---INI-- -zend_test.zend_mm_observer.enabled=0 -opcache.enable=0 ---FILE-- - ---EXPECTF-- -malloc 0x%s of size %d (block: %d) -malloc 0x%s of size %d (block: %d) -freed 0x%s of size %d diff --git a/ext/zend_test/tests/zend_mm_observer_realloc_01.phpt b/ext/zend_test/tests/zend_mm_observer_realloc_01.phpt new file mode 100644 index 000000000000..f3ad440bc982 --- /dev/null +++ b/ext/zend_test/tests/zend_mm_observer_realloc_01.phpt @@ -0,0 +1,24 @@ +--TEST-- +ZendMM Observer: Observe realloc +--EXTENSIONS-- +zend_test +--INI-- +zend_test.zend_mm_observer.enabled=0 +opcache.enable=0 +--FILE-- + +--EXPECTREGEX-- +.*realloc 0x\S+ of size \d+ \(block: \d+, former 0x\S+\) diff --git a/ext/zend_test/zend_mm_observer.c b/ext/zend_test/zend_mm_observer.c index 15c79f9ac9f8..242029c4b4c4 100644 --- a/ext/zend_test/zend_mm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -28,6 +28,7 @@ static void zend_mm_test_observer_malloc(size_t len, void *ptr ZEND_FILE_LINE_DC block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); } printf("malloc %p of size %zu (block: %zu)\n", ptr, len, block_len); + fflush(stdout); } static void zend_mm_test_observer_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) @@ -37,6 +38,7 @@ static void zend_mm_test_observer_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LIN block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); } printf("freed %p of size %zu\n", ptr, block_len); + fflush(stdout); } static void zend_mm_test_observer_realloc(void *ptr, size_t len, void *newptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) @@ -46,6 +48,7 @@ static void zend_mm_test_observer_realloc(void *ptr, size_t len, void *newptr ZE block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); } printf("realloc %p of size %zu (block: %zu, former %p)\n", newptr, len, block_len, ptr); + fflush(stdout); } static PHP_INI_MH(OnUpdateZendTestMMObserverEnabled) From 2c70e105ef963ff17cf013f68be26e235fba0920 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Tue, 1 Aug 2023 10:22:52 +0200 Subject: [PATCH 16/27] fix tests on windows --- ext/zend_test/tests/zend_mm_observer_free_01.phpt | 2 +- ext/zend_test/tests/zend_mm_observer_malloc_01.phpt | 2 +- ext/zend_test/tests/zend_mm_observer_realloc_01.phpt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/zend_test/tests/zend_mm_observer_free_01.phpt b/ext/zend_test/tests/zend_mm_observer_free_01.phpt index 44747b9694a6..1d0a9ec39c49 100644 --- a/ext/zend_test/tests/zend_mm_observer_free_01.phpt +++ b/ext/zend_test/tests/zend_mm_observer_free_01.phpt @@ -13,4 +13,4 @@ unset($string); ini_set('zend_test.zend_mm_observer.enabled', 'false'); ?> --EXPECTREGEX-- -.*freed 0x\S+ of size \d+.* +.*freed \S+ of size \d+.* diff --git a/ext/zend_test/tests/zend_mm_observer_malloc_01.phpt b/ext/zend_test/tests/zend_mm_observer_malloc_01.phpt index ccaeb690fd2e..1ae00b3ab94d 100644 --- a/ext/zend_test/tests/zend_mm_observer_malloc_01.phpt +++ b/ext/zend_test/tests/zend_mm_observer_malloc_01.phpt @@ -12,4 +12,4 @@ $string = str_repeat("ZendMM Observer", 100); ini_set('zend_test.zend_mm_observer.enabled', 'false'); ?> --EXPECTREGEX-- -.*malloc 0x\S+ of size \d+ \(block: \d+\).* +.*malloc \S+ of size \d+ \(block: \d+\).* diff --git a/ext/zend_test/tests/zend_mm_observer_realloc_01.phpt b/ext/zend_test/tests/zend_mm_observer_realloc_01.phpt index f3ad440bc982..a1f7e002812b 100644 --- a/ext/zend_test/tests/zend_mm_observer_realloc_01.phpt +++ b/ext/zend_test/tests/zend_mm_observer_realloc_01.phpt @@ -21,4 +21,4 @@ $a[] = 'ZendMM Observer'; ini_set('zend_test.zend_mm_observer.enabled', 'false'); ?> --EXPECTREGEX-- -.*realloc 0x\S+ of size \d+ \(block: \d+, former 0x\S+\) +.*realloc \S+ of size \d+ \(block: \d+, former \S+\) From 60819d607eb6d9df658e1ea8a77956b484d1594c Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Wed, 2 Aug 2023 12:04:24 +0200 Subject: [PATCH 17/27] fix asan tests --- ext/zend_test/tests/zend_mm_observer_all_01.phpt | 9 ++++----- ext/zend_test/zend_mm_observer.c | 12 +++++++----- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/ext/zend_test/tests/zend_mm_observer_all_01.phpt b/ext/zend_test/tests/zend_mm_observer_all_01.phpt index b26eb3d13ca6..07f2619d06e0 100644 --- a/ext/zend_test/tests/zend_mm_observer_all_01.phpt +++ b/ext/zend_test/tests/zend_mm_observer_all_01.phpt @@ -4,12 +4,11 @@ ZendMM Observer: Observe all zend_test --INI-- zend_test.zend_mm_observer.enabled=1 -opcache.enable=0 --FILE-- --EXPECTREGEX-- -.* -ZendMM Observer enabled -.* -ZendMM Observer disabled +.*ZendMM Observer enabled.* +.*done\..* +.*ZendMM Observer disabled.* diff --git a/ext/zend_test/zend_mm_observer.c b/ext/zend_test/zend_mm_observer.c index 242029c4b4c4..217830362908 100644 --- a/ext/zend_test/zend_mm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -24,7 +24,7 @@ static void zend_mm_test_observer_malloc(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { size_t block_len = 0; - if (is_zend_ptr(ptr)) { + if (is_zend_mm() && is_zend_ptr(ptr)) { block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); } printf("malloc %p of size %zu (block: %zu)\n", ptr, len, block_len); @@ -34,7 +34,7 @@ static void zend_mm_test_observer_malloc(size_t len, void *ptr ZEND_FILE_LINE_DC static void zend_mm_test_observer_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { size_t block_len = 0; - if (is_zend_ptr(ptr)) { + if (is_zend_mm() && is_zend_ptr(ptr)) { block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); } printf("freed %p of size %zu\n", ptr, block_len); @@ -44,7 +44,7 @@ static void zend_mm_test_observer_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LIN static void zend_mm_test_observer_realloc(void *ptr, size_t len, void *newptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { size_t block_len = 0; - if (is_zend_ptr(ptr)) { + if (is_zend_mm() && is_zend_ptr(ptr)) { block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); } printf("realloc %p of size %zu (block: %zu, former %p)\n", newptr, len, block_len, ptr); @@ -88,16 +88,18 @@ void zend_test_mm_observer_minit(INIT_FUNC_ARGS) void zend_test_mm_observer_rinit(void) { if (ZT_G(zend_mm_observer_enabled)) { - printf("ZendMM Observer enabled\n"); ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), zend_mm_test_observer_malloc, zend_mm_test_observer_free, zend_mm_test_observer_realloc); + printf("ZendMM Observer enabled\n"); + fflush(stdout); } } void zend_test_mm_observer_rshutdown(void) { if (ZT_G(observer)) { - printf("ZendMM Observer disabled\n"); zend_mm_observer_unregister(zend_mm_get_heap(), ZT_G(observer)); + printf("ZendMM Observer disabled\n"); + fflush(stdout); } ZT_G(observer) = NULL; } From 5578359ea50dbeadff1d40dfe68ba9e18c04c92c Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Thu, 3 Aug 2023 11:40:24 +0200 Subject: [PATCH 18/27] remove `is_zend_mm()` check --- ext/zend_test/zend_mm_observer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/zend_test/zend_mm_observer.c b/ext/zend_test/zend_mm_observer.c index 217830362908..e7f7b7331743 100644 --- a/ext/zend_test/zend_mm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -24,7 +24,7 @@ static void zend_mm_test_observer_malloc(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { size_t block_len = 0; - if (is_zend_mm() && is_zend_ptr(ptr)) { + if (is_zend_ptr(ptr)) { block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); } printf("malloc %p of size %zu (block: %zu)\n", ptr, len, block_len); @@ -34,7 +34,7 @@ static void zend_mm_test_observer_malloc(size_t len, void *ptr ZEND_FILE_LINE_DC static void zend_mm_test_observer_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { size_t block_len = 0; - if (is_zend_mm() && is_zend_ptr(ptr)) { + if (is_zend_ptr(ptr)) { block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); } printf("freed %p of size %zu\n", ptr, block_len); @@ -44,7 +44,7 @@ static void zend_mm_test_observer_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LIN static void zend_mm_test_observer_realloc(void *ptr, size_t len, void *newptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { size_t block_len = 0; - if (is_zend_mm() && is_zend_ptr(ptr)) { + if (is_zend_ptr(ptr)) { block_len = zend_mm_block_size(zend_mm_get_heap(), ptr); } printf("realloc %p of size %zu (block: %zu, former %p)\n", newptr, len, block_len, ptr); From b6e481c1f623c860bf1378bf9f34962ccdd6aab5 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Thu, 3 Aug 2023 13:39:43 +0200 Subject: [PATCH 19/27] Add missing author --- ext/zend_test/zend_mm_observer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/zend_test/zend_mm_observer.c b/ext/zend_test/zend_mm_observer.c index e7f7b7331743..68b43dd94474 100644 --- a/ext/zend_test/zend_mm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -10,7 +10,7 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: | + | Author: Florian Engelhardt | +----------------------------------------------------------------------+ */ From 9b4497831ef3762cf053464f1cd67b3bf643c325 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Fri, 27 Oct 2023 11:20:43 +0200 Subject: [PATCH 20/27] observe ZendMM garbage collection --- .../tests/zend_mm_observer_gc_01.phpt | 15 +++++++++++++ ext/zend_test/zend_mm_observer.c | 22 +++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 ext/zend_test/tests/zend_mm_observer_gc_01.phpt diff --git a/ext/zend_test/tests/zend_mm_observer_gc_01.phpt b/ext/zend_test/tests/zend_mm_observer_gc_01.phpt new file mode 100644 index 000000000000..7d828984afcd --- /dev/null +++ b/ext/zend_test/tests/zend_mm_observer_gc_01.phpt @@ -0,0 +1,15 @@ +--TEST-- +ZendMM Observer: Observe garbage collection +--EXTENSIONS-- +zend_test +--INI-- +zend_test.zend_mm_observer.enabled=0 +opcache.enable=0 +--FILE-- + +--EXPECTREGEX-- +.*garbage collection ended with \d+ bytes collected.* diff --git a/ext/zend_test/zend_mm_observer.c b/ext/zend_test/zend_mm_observer.c index 68b43dd94474..14f20e547d1c 100644 --- a/ext/zend_test/zend_mm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -31,6 +31,12 @@ static void zend_mm_test_observer_malloc(size_t len, void *ptr ZEND_FILE_LINE_DC fflush(stdout); } +static void zend_mm_test_observer_gc(size_t len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + printf("garbage collection ended with %zu bytes collected\n", len); + fflush(stdout); +} + static void zend_mm_test_observer_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { size_t block_len = 0; @@ -61,7 +67,13 @@ static PHP_INI_MH(OnUpdateZendTestMMObserverEnabled) if (int_value == 1) { if (ZT_G(observer) == NULL) { - ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), zend_mm_test_observer_malloc, zend_mm_test_observer_free, zend_mm_test_observer_realloc); + ZT_G(observer) = zend_mm_observer_register( + zend_mm_get_heap(), + zend_mm_test_observer_malloc, + zend_mm_test_observer_free, + zend_mm_test_observer_realloc, + zend_mm_test_observer_gc + ); } } else { if (ZT_G(observer) != NULL) { @@ -88,7 +100,13 @@ void zend_test_mm_observer_minit(INIT_FUNC_ARGS) void zend_test_mm_observer_rinit(void) { if (ZT_G(zend_mm_observer_enabled)) { - ZT_G(observer) = zend_mm_observer_register(zend_mm_get_heap(), zend_mm_test_observer_malloc, zend_mm_test_observer_free, zend_mm_test_observer_realloc); + ZT_G(observer) = zend_mm_observer_register( + zend_mm_get_heap(), + zend_mm_test_observer_malloc, + zend_mm_test_observer_free, + zend_mm_test_observer_realloc, + zend_mm_test_observer_gc + ); printf("ZendMM Observer enabled\n"); fflush(stdout); } From 19434e32a99a77ec93bd640eeddd3579303e27bf Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Fri, 27 Oct 2023 13:08:41 +0200 Subject: [PATCH 21/27] Add shutdown observer and fix debug builds --- .../tests/zend_mm_observer_shutdown_01.phpt | 12 +++++++++ ext/zend_test/zend_mm_observer.c | 25 ++++++++++++------- 2 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 ext/zend_test/tests/zend_mm_observer_shutdown_01.phpt diff --git a/ext/zend_test/tests/zend_mm_observer_shutdown_01.phpt b/ext/zend_test/tests/zend_mm_observer_shutdown_01.phpt new file mode 100644 index 000000000000..664a52af6884 --- /dev/null +++ b/ext/zend_test/tests/zend_mm_observer_shutdown_01.phpt @@ -0,0 +1,12 @@ +--TEST-- +ZendMM Observer: Observe shutdown +--EXTENSIONS-- +zend_test +--INI-- +zend_test.zend_mm_observer.enabled=1 +--FILE-- + +--EXPECTREGEX-- +.*shutdown in progress: full\(0\), silent\(1\).* diff --git a/ext/zend_test/zend_mm_observer.c b/ext/zend_test/zend_mm_observer.c index 14f20e547d1c..7ea7ef7ce2b2 100644 --- a/ext/zend_test/zend_mm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -31,12 +31,6 @@ static void zend_mm_test_observer_malloc(size_t len, void *ptr ZEND_FILE_LINE_DC fflush(stdout); } -static void zend_mm_test_observer_gc(size_t len ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -{ - printf("garbage collection ended with %zu bytes collected\n", len); - fflush(stdout); -} - static void zend_mm_test_observer_free(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { size_t block_len = 0; @@ -57,6 +51,18 @@ static void zend_mm_test_observer_realloc(void *ptr, size_t len, void *newptr ZE fflush(stdout); } +static void zend_mm_test_observer_gc(size_t len) +{ + printf("garbage collection ended with %zu bytes collected\n", len); + fflush(stdout); +} + +static void zend_mm_test_observer_shutdown(bool full, bool silent) +{ + printf("shutdown in progress: full(%d), silent(%d)\n", full, silent); + fflush(stdout); +} + static PHP_INI_MH(OnUpdateZendTestMMObserverEnabled) { if (new_value == NULL) { @@ -72,7 +78,8 @@ static PHP_INI_MH(OnUpdateZendTestMMObserverEnabled) zend_mm_test_observer_malloc, zend_mm_test_observer_free, zend_mm_test_observer_realloc, - zend_mm_test_observer_gc + zend_mm_test_observer_gc, + zend_mm_test_observer_shutdown ); } } else { @@ -105,7 +112,8 @@ void zend_test_mm_observer_rinit(void) zend_mm_test_observer_malloc, zend_mm_test_observer_free, zend_mm_test_observer_realloc, - zend_mm_test_observer_gc + zend_mm_test_observer_gc, + zend_mm_test_observer_shutdown ); printf("ZendMM Observer enabled\n"); fflush(stdout); @@ -121,4 +129,3 @@ void zend_test_mm_observer_rshutdown(void) } ZT_G(observer) = NULL; } - From be9b8795101af59811c512cf73be47bd5bdb7ca5 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Mon, 10 Nov 2025 15:49:45 +0100 Subject: [PATCH 22/27] Fix remaining conflict markers from rebase --- Zend/zend_alloc.c | 169 ---------------------------------------------- Zend/zend_alloc.h | 11 --- 2 files changed, 180 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 25c18f48a9a6..138009eb1382 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -232,21 +232,11 @@ typedef struct _zend_mm_huge_list zend_mm_huge_list; static bool zend_mm_use_huge_pages = false; struct _zend_mm_observer { -<<<<<<< HEAD void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); void (*gc)(size_t len); void (*shutdown)(bool full, bool silent); -||||||| parent of d96128265e4 (Add parameter names) - void (*malloc)(size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); - void (*free)(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); - void (*realloc)(void *, size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); -======= - void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); - void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); - void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ->>>>>>> d96128265e4 (Add parameter names) zend_mm_observer *next; }; @@ -2735,153 +2725,6 @@ ZEND_API bool is_zend_ptr(const void *ptr) return 0; } -<<<<<<< HEAD -||||||| parent of e5d60ddb2c4 (deduplicate observer calling) -#if ZEND_MM_CUSTOM - -static ZEND_COLD void* ZEND_FASTCALL _malloc_custom(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -{ - void *ptr; - zend_mm_heap *heap = AG(mm_heap); - int use_custom_heap = heap->use_custom_heap; - if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) { - ptr = heap->custom_heap.debug._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } else if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_STD) { - ptr = heap->custom_heap.std._malloc(size); - } else { - // no custom memory manager, only observer present - ptr = zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } - if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { - zend_mm_observer *current = heap->observers; - while (current != NULL) { - if (current->malloc != NULL) { - current->malloc(size, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } - current = current->next; - } - } - return ptr; -} - -static ZEND_COLD void ZEND_FASTCALL _efree_custom(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -{ - zend_mm_heap *heap = AG(mm_heap); - int use_custom_heap = heap->use_custom_heap; - - if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { - zend_mm_observer *current = heap->observers; - while (current != NULL) { - if (current->free != NULL) { - current->free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } - current = current->next; - } - } - - if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) { - heap->custom_heap.debug._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } else if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_STD) { - heap->custom_heap.std._free(ptr); - } else { - // no custom memory manager, only observer present - zend_mm_free_heap(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } -} - -static ZEND_COLD void* ZEND_FASTCALL _realloc_custom(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -{ - void *new_ptr; - zend_mm_heap *heap = AG(mm_heap); - int use_custom_heap = heap->use_custom_heap; - if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) { - new_ptr = heap->custom_heap.debug._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } else if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_STD) { - new_ptr = heap->custom_heap.std._realloc(ptr, size); - } else { - // no custom memory manager, only observer present - new_ptr = zend_mm_realloc_heap(AG(mm_heap), ptr, size, 0, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } - if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { - zend_mm_observer *current = heap->observers; - while (current != NULL) { - if (current->realloc != NULL) { - current->realloc(ptr, size, new_ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } - current = current->next; - } - } - return new_ptr; -} -#endif - -======= -#if ZEND_MM_CUSTOM - -#define HANDLE_OBSERVERS(observer_function, ...) \ - if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { \ - zend_mm_observer *current = heap->observers; \ - while (current != NULL) { \ - if (current->observer_function != NULL) { \ - current->observer_function(__VA_ARGS__ ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ - } \ - current = current->next; \ - } \ - } - -static ZEND_COLD void* ZEND_FASTCALL _malloc_custom(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -{ - void *ptr; - zend_mm_heap *heap = AG(mm_heap); - int use_custom_heap = heap->use_custom_heap; - if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) { - ptr = heap->custom_heap.debug._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } else if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_STD) { - ptr = heap->custom_heap.std._malloc(size); - } else { - // no custom memory manager, only observer present - ptr = zend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } - HANDLE_OBSERVERS(malloc, size, ptr) - return ptr; -} - -static ZEND_COLD void ZEND_FASTCALL _efree_custom(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -{ - zend_mm_heap *heap = AG(mm_heap); - int use_custom_heap = heap->use_custom_heap; - - HANDLE_OBSERVERS(free, ptr) - - if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) { - heap->custom_heap.debug._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } else if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_STD) { - heap->custom_heap.std._free(ptr); - } else { - // no custom memory manager, only observer present - zend_mm_free_heap(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } -} - -static ZEND_COLD void* ZEND_FASTCALL _realloc_custom(void *ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -{ - void *new_ptr; - zend_mm_heap *heap = AG(mm_heap); - int use_custom_heap = heap->use_custom_heap; - if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) { - new_ptr = heap->custom_heap.debug._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } else if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_STD) { - new_ptr = heap->custom_heap.std._realloc(ptr, size); - } else { - // no custom memory manager, only observer present - new_ptr = zend_mm_realloc_heap(AG(mm_heap), ptr, size, 0, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } - HANDLE_OBSERVERS(realloc, ptr, size, new_ptr) - return new_ptr; -} -#endif - ->>>>>>> e5d60ddb2c4 (deduplicate observer calling) #if !ZEND_DEBUG && defined(HAVE_BUILTIN_CONSTANT_P) #undef _emalloc @@ -3736,24 +3579,12 @@ ZEND_API void zend_mm_get_custom_handlers_ex(zend_mm_heap *heap, } ZEND_API zend_mm_observer* zend_mm_observer_register( -<<<<<<< HEAD zend_mm_heap *heap, void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*gc)(size_t len), void (*shutdown)(bool full, bool silent) -||||||| parent of d96128265e4 (Add parameter names) - zend_mm_heap* heap, - void (*malloc)(size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void (*free)(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void (*realloc)(void *, size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -======= - zend_mm_heap* heap, - void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ->>>>>>> d96128265e4 (Add parameter names) ) { #if ZEND_MM_CUSTOM if (heap == NULL) { diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index fee8506a31f6..d90ec4c89cf5 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -301,22 +301,11 @@ typedef struct _zend_mm_observer zend_mm_observer; ZEND_API bool zend_mm_is_observed(zend_mm_heap *heap); ZEND_API zend_mm_observer* zend_mm_observer_register( zend_mm_heap *heap, -<<<<<<< HEAD void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*gc)(size_t len), void (*shutdown)(bool full, bool silent) -||||||| parent of d96128265e4 (Add parameter names) - void (*malloc)(size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void (*free)(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void (*realloc)(void *, size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -======= - void (*malloc)(size_t len, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void (*free)(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void (*realloc)(void *old_ptr, size_t len, void *new_ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) - ->>>>>>> d96128265e4 (Add parameter names) ); ZEND_API bool zend_mm_observer_unregister(zend_mm_heap *heap, zend_mm_observer *observer); void zend_mm_observers_shutdown(zend_mm_heap *heap); From f8ab266a738cab7c86ad76720ae095f57b778522 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Mon, 10 Nov 2025 17:26:16 +0100 Subject: [PATCH 23/27] fixup after rebase --- Zend/zend_alloc.c | 62 +++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 40 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 138009eb1382..2cd16b59fd6e 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -240,17 +240,6 @@ struct _zend_mm_observer { zend_mm_observer *next; }; -#define HANDLE_NO_DEBUG_OBSERVERS(observer_function, ...) \ - if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { \ - zend_mm_observer *current = heap->observers; \ - while (current != NULL) { \ - if (current->observer_function != NULL) { \ - current->observer_function(__VA_ARGS__); \ - } \ - current = current->next; \ - } \ - } - #define HANDLE_OBSERVERS(observer_function, ...) \ if (use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { \ zend_mm_observer *current = heap->observers; \ @@ -295,21 +284,6 @@ struct _zend_mm_observer { */ -struct _zend_mm_observer { - void (*malloc)(size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); - void (*free)(void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); - void (*realloc)(void *, size_t, void * ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); - zend_mm_observer *next; -}; -zend_mm_observer *zend_mm_observers = NULL; - -typedef struct _zend_mm_heap_observer zend_mm_heap_observer; -struct _zend_mm_heap_observer { - zend_mm_observer *observer; - bool enabled; - zend_mm_heap_observer *next; -}; - struct _zend_mm_heap { #if ZEND_MM_CUSTOM int use_custom_heap; /* bitflag */ @@ -2135,7 +2109,6 @@ static zend_mm_heap *zend_mm_init(void) #if ZEND_MM_CUSTOM heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_NONE; heap->observers = NULL; - zend_mm_observers_startup(heap); #endif #if ZEND_MM_STORAGE heap->storage = NULL; @@ -2166,7 +2139,15 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap) } return 0; } - HANDLE_NO_DEBUG_OBSERVERS(gc, collected) + if (heap->use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { + zend_mm_observer *current = heap->observers; + while (current != NULL) { + if (current->gc != NULL) { + current->gc(collected); + } + current = current->next; + } + } #endif for (i = 0; i < ZEND_MM_BINS; i++) { @@ -2486,6 +2467,19 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) zend_mm_chunk *p; zend_mm_huge_list *list; + // Call observer shutdown callbacks before cleaning up +#if ZEND_MM_CUSTOM + if (heap->use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { + zend_mm_observer *current = heap->observers; + while (current != NULL) { + if (current->shutdown != NULL) { + current->shutdown(full, silent); + } + current = current->next; + } + } +#endif + if (full == false) { zend_mm_observers_shutdown(heap); } @@ -2519,8 +2513,6 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) shutdown(full, silent); } - HANDLE_NO_DEBUG_OBSERVERS(shutdown, full, silent) - return; } #endif @@ -3416,7 +3408,6 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals) mm_heap->tracked_allocs = malloc(sizeof(HashTable)); zend_hash_init(mm_heap->tracked_allocs, 1024, NULL, NULL, 1); } - zend_mm_observers_startup(mm_heap); return; } #endif @@ -3483,15 +3474,6 @@ ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap) #endif } -ZEND_API bool zend_mm_is_observed(zend_mm_heap *new_heap) -{ -#if ZEND_MM_CUSTOM - return (AG(mm_heap)->use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) != 0; -#else - return false; -#endif -} - ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), From ed365398376daac5d07b730ff63602a5fbdbe74d Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Wed, 12 Nov 2025 12:58:20 +0100 Subject: [PATCH 24/27] fix tests --- ext/zend_test/tests/zend_mm_observer_all_01.phpt | 11 +++++++++-- ext/zend_test/tests/zend_mm_observer_realloc_01.phpt | 4 +++- ext/zend_test/zend_mm_observer.c | 6 +++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/ext/zend_test/tests/zend_mm_observer_all_01.phpt b/ext/zend_test/tests/zend_mm_observer_all_01.phpt index 07f2619d06e0..10aca1a9a8a7 100644 --- a/ext/zend_test/tests/zend_mm_observer_all_01.phpt +++ b/ext/zend_test/tests/zend_mm_observer_all_01.phpt @@ -10,5 +10,12 @@ echo "done."; ?> --EXPECTREGEX-- .*ZendMM Observer enabled.* -.*done\..* -.*ZendMM Observer disabled.* +(malloc|freed|realloc).* +(malloc|freed|realloc).* +(malloc|freed|realloc).* +(malloc|freed|realloc).* +(malloc|freed|realloc).* +(malloc|freed|realloc).* +(malloc|freed|realloc).* +.*shutdown in progress: full\(0\), silent\(1\).* +.*done\..*ZendMM Observer disabled.* diff --git a/ext/zend_test/tests/zend_mm_observer_realloc_01.phpt b/ext/zend_test/tests/zend_mm_observer_realloc_01.phpt index a1f7e002812b..46ce15a8bc3d 100644 --- a/ext/zend_test/tests/zend_mm_observer_realloc_01.phpt +++ b/ext/zend_test/tests/zend_mm_observer_realloc_01.phpt @@ -21,4 +21,6 @@ $a[] = 'ZendMM Observer'; ini_set('zend_test.zend_mm_observer.enabled', 'false'); ?> --EXPECTREGEX-- -.*realloc \S+ of size \d+ \(block: \d+, former \S+\) +.*ZendMM Observer enabled.* +.*realloc \S+ of size \d+ \(block: \d+, former \S+\).* +.*ZendMM Observer disabled.* diff --git a/ext/zend_test/zend_mm_observer.c b/ext/zend_test/zend_mm_observer.c index 7ea7ef7ce2b2..af2e8b0e0de8 100644 --- a/ext/zend_test/zend_mm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -81,11 +81,15 @@ static PHP_INI_MH(OnUpdateZendTestMMObserverEnabled) zend_mm_test_observer_gc, zend_mm_test_observer_shutdown ); + printf("ZendMM Observer enabled\n"); + fflush(stdout); } } else { if (ZT_G(observer) != NULL) { zend_mm_observer_unregister(zend_mm_get_heap(), ZT_G(observer)); ZT_G(observer) = NULL; + printf("ZendMM Observer disabled\n"); + fflush(stdout); } } return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); @@ -106,7 +110,7 @@ void zend_test_mm_observer_minit(INIT_FUNC_ARGS) void zend_test_mm_observer_rinit(void) { - if (ZT_G(zend_mm_observer_enabled)) { + if (ZT_G(zend_mm_observer_enabled) && ZT_G(observer) == NULL) { ZT_G(observer) = zend_mm_observer_register( zend_mm_get_heap(), zend_mm_test_observer_malloc, From 3efcffca000b2db496f0e9f93e59afa6500d318d Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Wed, 12 Nov 2025 12:58:39 +0100 Subject: [PATCH 25/27] fix gc with custom gc --- Zend/zend_alloc.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 2cd16b59fd6e..2b961efc7ff8 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2135,18 +2135,18 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap) if (heap->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { size_t (*gc)(void) = heap->custom_heap._gc; if (gc) { - return gc(); + collected = gc(); } - return 0; - } - if (heap->use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { - zend_mm_observer *current = heap->observers; - while (current != NULL) { - if (current->gc != NULL) { - current->gc(collected); + if (heap->use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { + zend_mm_observer *current = heap->observers; + while (current != NULL) { + if (current->gc != NULL) { + current->gc(collected); + } + current = current->next; } - current = current->next; } + return collected; } #endif @@ -2252,7 +2252,20 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap) } } while (chunk != heap->main_chunk); - return collected * ZEND_MM_PAGE_SIZE; + size_t collected_bytes = collected * ZEND_MM_PAGE_SIZE; +#if ZEND_MM_CUSTOM + if (heap->use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { + zend_mm_observer *current = heap->observers; + while (current != NULL) { + if (current->gc != NULL) { + current->gc(collected_bytes); + } + current = current->next; + } + } +#endif + + return collected_bytes; } #if ZEND_DEBUG From 9f9462f4fcefe26a88cf1bee516a23827a2963e0 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Wed, 12 Nov 2025 18:09:18 +0100 Subject: [PATCH 26/27] fixup --- Zend/zend_alloc.c | 4 +- .../tests/zend_mm_observer_all_01.phpt | 21 -------- .../tests/zend_mm_observer_lifecycle_01.phpt | 13 +++++ .../tests/zend_mm_observer_shutdown_01.phpt | 4 +- ext/zend_test/zend_mm_observer.c | 48 +++++++++++-------- 5 files changed, 46 insertions(+), 44 deletions(-) delete mode 100644 ext/zend_test/tests/zend_mm_observer_all_01.phpt create mode 100644 ext/zend_test/tests/zend_mm_observer_lifecycle_01.phpt diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 2b961efc7ff8..0dbae5c258ca 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2735,12 +2735,12 @@ ZEND_API bool is_zend_ptr(const void *ptr) #if ZEND_MM_CUSTOM # define ZEND_MM_CUSTOM_ALLOCATOR(size) do { \ - if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { \ + if (UNEXPECTED(AG(mm_heap)->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED)) { \ return AG(mm_heap)->custom_heap._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ } \ } while (0) # define ZEND_MM_CUSTOM_DEALLOCATOR(ptr) do { \ - if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) { \ + if (UNEXPECTED(AG(mm_heap)->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED)) { \ AG(mm_heap)->custom_heap._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ return; \ } \ diff --git a/ext/zend_test/tests/zend_mm_observer_all_01.phpt b/ext/zend_test/tests/zend_mm_observer_all_01.phpt deleted file mode 100644 index 10aca1a9a8a7..000000000000 --- a/ext/zend_test/tests/zend_mm_observer_all_01.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -ZendMM Observer: Observe all ---EXTENSIONS-- -zend_test ---INI-- -zend_test.zend_mm_observer.enabled=1 ---FILE-- - ---EXPECTREGEX-- -.*ZendMM Observer enabled.* -(malloc|freed|realloc).* -(malloc|freed|realloc).* -(malloc|freed|realloc).* -(malloc|freed|realloc).* -(malloc|freed|realloc).* -(malloc|freed|realloc).* -(malloc|freed|realloc).* -.*shutdown in progress: full\(0\), silent\(1\).* -.*done\..*ZendMM Observer disabled.* diff --git a/ext/zend_test/tests/zend_mm_observer_lifecycle_01.phpt b/ext/zend_test/tests/zend_mm_observer_lifecycle_01.phpt new file mode 100644 index 000000000000..9c1a6f2b6a66 --- /dev/null +++ b/ext/zend_test/tests/zend_mm_observer_lifecycle_01.phpt @@ -0,0 +1,13 @@ +--TEST-- +ZendMM Observer: Observe lifecycle (RINIT -> RSHUTDOWN) +--EXTENSIONS-- +zend_test +--INI-- +zend_test.zend_mm_observer.enabled=1 +opcache.enable=0 +--FILE-- + +--EXPECTREGEX-- +.*ZendMM Observer enabled.* diff --git a/ext/zend_test/tests/zend_mm_observer_shutdown_01.phpt b/ext/zend_test/tests/zend_mm_observer_shutdown_01.phpt index 664a52af6884..50a0f8020243 100644 --- a/ext/zend_test/tests/zend_mm_observer_shutdown_01.phpt +++ b/ext/zend_test/tests/zend_mm_observer_shutdown_01.phpt @@ -2,6 +2,8 @@ ZendMM Observer: Observe shutdown --EXTENSIONS-- zend_test +--ENV-- +ZEND_TEST_MM_OBSERVER_SHUTDOWN_TEST=1 --INI-- zend_test.zend_mm_observer.enabled=1 --FILE-- @@ -9,4 +11,4 @@ zend_test.zend_mm_observer.enabled=1 echo "done."; ?> --EXPECTREGEX-- -.*shutdown in progress: full\(0\), silent\(1\).* +.*shutdown in progress: full\(\d\), silent\(\d\).* diff --git a/ext/zend_test/zend_mm_observer.c b/ext/zend_test/zend_mm_observer.c index af2e8b0e0de8..75d63c676887 100644 --- a/ext/zend_test/zend_mm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -71,25 +71,29 @@ static PHP_INI_MH(OnUpdateZendTestMMObserverEnabled) int int_value = zend_ini_parse_bool(new_value); - if (int_value == 1) { - if (ZT_G(observer) == NULL) { - ZT_G(observer) = zend_mm_observer_register( - zend_mm_get_heap(), - zend_mm_test_observer_malloc, - zend_mm_test_observer_free, - zend_mm_test_observer_realloc, - zend_mm_test_observer_gc, - zend_mm_test_observer_shutdown - ); - printf("ZendMM Observer enabled\n"); - fflush(stdout); - } - } else { - if (ZT_G(observer) != NULL) { - zend_mm_observer_unregister(zend_mm_get_heap(), ZT_G(observer)); - ZT_G(observer) = NULL; - printf("ZendMM Observer disabled\n"); - fflush(stdout); + // Only toggle observer during runtime (ini_set during active request) + // RINIT/RSHUTDOWN handle initialization and cleanup + if (stage == PHP_INI_STAGE_RUNTIME) { + if (int_value == 1) { + if (ZT_G(observer) == NULL) { + ZT_G(observer) = zend_mm_observer_register( + zend_mm_get_heap(), + zend_mm_test_observer_malloc, + zend_mm_test_observer_free, + zend_mm_test_observer_realloc, + zend_mm_test_observer_gc, + zend_mm_test_observer_shutdown + ); + printf("ZendMM Observer enabled\n"); + fflush(stdout); + } + } else { + if (ZT_G(observer) != NULL) { + zend_mm_observer_unregister(zend_mm_get_heap(), ZT_G(observer)); + ZT_G(observer) = NULL; + printf("ZendMM Observer disabled\n"); + fflush(stdout); + } } } return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); @@ -110,7 +114,7 @@ void zend_test_mm_observer_minit(INIT_FUNC_ARGS) void zend_test_mm_observer_rinit(void) { - if (ZT_G(zend_mm_observer_enabled) && ZT_G(observer) == NULL) { + if (ZT_G(zend_mm_observer_enabled)) { ZT_G(observer) = zend_mm_observer_register( zend_mm_get_heap(), zend_mm_test_observer_malloc, @@ -126,6 +130,10 @@ void zend_test_mm_observer_rinit(void) void zend_test_mm_observer_rshutdown(void) { + char *env = getenv("ZEND_TEST_MM_OBSERVER_SHUTDOWN_TEST"); + if (env != NULL) { + return; + } if (ZT_G(observer)) { zend_mm_observer_unregister(zend_mm_get_heap(), ZT_G(observer)); printf("ZendMM Observer disabled\n"); From d8ea60ea30fb8d4ed05a30aaa2695f5b2feb12ab Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Mon, 27 Apr 2026 16:37:26 +0200 Subject: [PATCH 27/27] cleanup --- Zend/zend_alloc.c | 197 +++++++++++++++++++------------ Zend/zend_alloc.h | 9 -- ext/zend_test/zend_mm_observer.c | 4 +- 3 files changed, 123 insertions(+), 87 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 0dbae5c258ca..8f05bca25405 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -50,7 +50,6 @@ * with more specialized routines when the requested size is known. */ -#include "php.h" #include "zend.h" #include "zend_alloc.h" #include "zend_globals.h" @@ -2480,24 +2479,21 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) zend_mm_chunk *p; zend_mm_huge_list *list; - // Call observer shutdown callbacks before cleaning up #if ZEND_MM_CUSTOM if (heap->use_custom_heap & ZEND_MM_CUSTOM_HEAP_OBSERVED) { zend_mm_observer *current = heap->observers; while (current != NULL) { + zend_mm_observer *next = current->next; if (current->shutdown != NULL) { current->shutdown(full, silent); } - current = current->next; + pefree(current, 1); + current = next; } - } -#endif - - if (full == false) { - zend_mm_observers_shutdown(heap); + heap->observers = NULL; + heap->use_custom_heap &= ~ZEND_MM_CUSTOM_HEAP_OBSERVED; } -#if ZEND_MM_CUSTOM if (heap->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { if (heap->custom_heap._malloc == tracked_malloc) { if (silent) { @@ -2651,7 +2647,7 @@ void* ZEND_FASTCALL _zend_mm_realloc2(zend_mm_heap *heap, void *ptr, size_t size ZEND_API size_t ZEND_FASTCALL _zend_mm_block_size(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { #if ZEND_MM_CUSTOM - if (UNEXPECTED(heap->use_custom_heap)) { + if (UNEXPECTED(heap->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED)) { if (heap->custom_heap._malloc == tracked_malloc) { zend_ulong h = ((uintptr_t) ptr) >> ZEND_MM_ALIGNMENT_LOG2; zval *size_zv = zend_hash_index_find(heap->tracked_allocs, h); @@ -2730,29 +2726,100 @@ ZEND_API bool is_zend_ptr(const void *ptr) return 0; } +#if ZEND_MM_CUSTOM +static ZEND_COLD void* ZEND_FASTCALL zend_mm_alloc_custom(zend_mm_heap *heap, int use_custom_heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + void *ptr; + + ZEND_ASSERT(use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED); + ptr = heap->custom_heap._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + HANDLE_OBSERVERS(malloc, size, ptr) + + return ptr; +} + +static ZEND_COLD void ZEND_FASTCALL zend_mm_free_custom(zend_mm_heap *heap, int use_custom_heap, void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + ZEND_ASSERT(use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED); + HANDLE_OBSERVERS(free, ptr) + heap->custom_heap._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); +} +#endif + #if !ZEND_DEBUG && defined(HAVE_BUILTIN_CONSTANT_P) #undef _emalloc #if ZEND_MM_CUSTOM -# define ZEND_MM_CUSTOM_ALLOCATOR(size) do { \ - if (UNEXPECTED(AG(mm_heap)->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED)) { \ - return AG(mm_heap)->custom_heap._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ +# define ZEND_MM_OBSERVED_BIN_ALLOCATOR(_size, _num, _min_size) do { \ + zend_mm_heap *heap = AG(mm_heap); \ + int use_custom_heap = heap->use_custom_heap; \ + if (UNEXPECTED(use_custom_heap)) { \ + void *ptr; \ + if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { \ + return zend_mm_alloc_custom(heap, use_custom_heap, _size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ + } \ + if (_size < _min_size) { \ + ptr = zend_mm_alloc_small(heap, ZEND_MM_SMALL_SIZE_TO_BIN(_min_size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ + } else { \ + ptr = zend_mm_alloc_small(heap, _num ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ + } \ + HANDLE_OBSERVERS(malloc, _size, ptr) \ + return ptr; \ + } \ + } while (0) +# define ZEND_MM_OBSERVED_ALLOCATOR(size, allocation) do { \ + zend_mm_heap *heap = AG(mm_heap); \ + int use_custom_heap = heap->use_custom_heap; \ + if (UNEXPECTED(use_custom_heap)) { \ + void *ptr; \ + if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { \ + return zend_mm_alloc_custom(heap, use_custom_heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ + } \ + ptr = (allocation); \ + HANDLE_OBSERVERS(malloc, size, ptr) \ + return ptr; \ + } \ + } while (0) +# define ZEND_MM_OBSERVED_DEALLOCATOR(ptr, deallocation) do { \ + zend_mm_heap *heap = AG(mm_heap); \ + int use_custom_heap = heap->use_custom_heap; \ + if (UNEXPECTED(use_custom_heap)) { \ + if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { \ + zend_mm_free_custom(heap, use_custom_heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ + return; \ + } \ + HANDLE_OBSERVERS(free, ptr) \ + deallocation; \ + return; \ } \ } while (0) -# define ZEND_MM_CUSTOM_DEALLOCATOR(ptr) do { \ - if (UNEXPECTED(AG(mm_heap)->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED)) { \ - AG(mm_heap)->custom_heap._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ +# define ZEND_MM_OBSERVED_BIN_DEALLOCATOR(ptr, _size, _min_size, deallocation) do { \ + zend_mm_heap *heap = AG(mm_heap); \ + int use_custom_heap = heap->use_custom_heap; \ + if (UNEXPECTED(use_custom_heap)) { \ + if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { \ + zend_mm_free_custom(heap, use_custom_heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); \ + return; \ + } \ + if (_size < _min_size) { \ + _efree_ ## _min_size(ptr); \ + return; \ + } \ + HANDLE_OBSERVERS(free, ptr) \ + deallocation; \ return; \ } \ } while (0) #else -# define ZEND_MM_CUSTOM_ALLOCATOR(size) -# define ZEND_MM_CUSTOM_DEALLOCATOR(ptr) +# define ZEND_MM_OBSERVED_BIN_ALLOCATOR(_size, _num, _min_size) +# define ZEND_MM_OBSERVED_ALLOCATOR(size, allocation) +# define ZEND_MM_OBSERVED_DEALLOCATOR(ptr, deallocation) +# define ZEND_MM_OBSERVED_BIN_DEALLOCATOR(ptr, _size, _min_size, deallocation) #endif # define _ZEND_BIN_ALLOCATOR(_num, _size, _elements, _pages, _min_size, y) \ ZEND_API void* ZEND_FASTCALL _emalloc_ ## _size(void) { \ - ZEND_MM_CUSTOM_ALLOCATOR(_size); \ + ZEND_MM_OBSERVED_BIN_ALLOCATOR(_size, _num, _min_size); \ if (_size < _min_size) { \ return _emalloc_ ## _min_size(); \ } \ @@ -2763,20 +2830,28 @@ ZEND_MM_BINS_INFO(_ZEND_BIN_ALLOCATOR, ZEND_MM_MIN_USEABLE_BIN_SIZE, y) ZEND_API void* ZEND_FASTCALL _emalloc_large(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) { - ZEND_MM_CUSTOM_ALLOCATOR(size); + ZEND_MM_OBSERVED_ALLOCATOR(size, zend_mm_alloc_large_ex(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC)); return zend_mm_alloc_large_ex(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } ZEND_API void* ZEND_FASTCALL _emalloc_huge(size_t size) { - ZEND_MM_CUSTOM_ALLOCATOR(size); + ZEND_MM_OBSERVED_ALLOCATOR(size, zend_mm_alloc_huge(heap, size)); return zend_mm_alloc_huge(AG(mm_heap), size); } #if ZEND_DEBUG # define _ZEND_BIN_FREE(_num, _size, _elements, _pages, _min_size, y) \ ZEND_API void ZEND_FASTCALL _efree_ ## _size(void *ptr) { \ - ZEND_MM_CUSTOM_DEALLOCATOR(ptr); \ + ZEND_MM_OBSERVED_BIN_DEALLOCATOR(ptr, _size, _min_size, { \ + size_t page_offset = ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE); \ + zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); \ + int page_num = page_offset / ZEND_MM_PAGE_SIZE; \ + ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted"); \ + ZEND_ASSERT(chunk->map[page_num] & ZEND_MM_IS_SRUN); \ + ZEND_ASSERT(ZEND_MM_SRUN_BIN_NUM(chunk->map[page_num]) == _num); \ + zend_mm_free_small(heap, ptr, _num); \ + }); \ if (_size < _min_size) { \ _efree_ ## _min_size(ptr); \ return; \ @@ -2794,7 +2869,11 @@ ZEND_API void* ZEND_FASTCALL _emalloc_huge(size_t size) #else # define _ZEND_BIN_FREE(_num, _size, _elements, _pages, _min_size, y) \ ZEND_API void ZEND_FASTCALL _efree_ ## _size(void *ptr) { \ - ZEND_MM_CUSTOM_DEALLOCATOR(ptr); \ + ZEND_MM_OBSERVED_BIN_DEALLOCATOR(ptr, _size, _min_size, { \ + zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); \ + ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted"); \ + zend_mm_free_small(heap, ptr, _num); \ + }); \ if (_size < _min_size) { \ _efree_ ## _min_size(ptr); \ return; \ @@ -2811,7 +2890,17 @@ ZEND_MM_BINS_INFO(_ZEND_BIN_FREE, ZEND_MM_MIN_USEABLE_BIN_SIZE, y) ZEND_API void ZEND_FASTCALL _efree_large(void *ptr, size_t size) { - ZEND_MM_CUSTOM_DEALLOCATOR(ptr); + ZEND_MM_OBSERVED_DEALLOCATOR(ptr, { + size_t page_offset = ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE); + zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); + int page_num = page_offset / ZEND_MM_PAGE_SIZE; + uint32_t pages_count = ZEND_MM_ALIGNED_SIZE_EX(size, ZEND_MM_PAGE_SIZE) / ZEND_MM_PAGE_SIZE; + + ZEND_MM_CHECK(chunk->heap == heap && ZEND_MM_ALIGNED_OFFSET(page_offset, ZEND_MM_PAGE_SIZE) == 0, "zend_mm_heap corrupted"); + ZEND_ASSERT(chunk->map[page_num] & ZEND_MM_IS_LRUN); + ZEND_ASSERT(ZEND_MM_LRUN_PAGES(chunk->map[page_num]) == pages_count); + zend_mm_free_large(heap, chunk, page_num, pages_count); + }); { size_t page_offset = ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE); zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); @@ -2828,7 +2917,7 @@ ZEND_API void ZEND_FASTCALL _efree_large(void *ptr, size_t size) ZEND_API void ZEND_FASTCALL _efree_huge(void *ptr, size_t size) { - ZEND_MM_CUSTOM_DEALLOCATOR(ptr); + ZEND_MM_OBSERVED_DEALLOCATOR(ptr, zend_mm_free_huge(heap, ptr)); zend_mm_free_huge(AG(mm_heap), ptr); } #endif @@ -2842,17 +2931,11 @@ ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LI if (UNEXPECTED(use_custom_heap)) { void *ptr; - // Check for actual custom handler (excluding observer bit) if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { - ptr = heap->custom_heap._malloc(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } else { - // No custom handler, use default heap - ptr = zend_mm_alloc_heap(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + return zend_mm_alloc_custom(heap, use_custom_heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } - - // Call observers if present + ptr = zend_mm_alloc_heap(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); HANDLE_OBSERVERS(malloc, size, ptr) - return ptr; } #endif @@ -2866,16 +2949,12 @@ ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_OR int use_custom_heap = heap->use_custom_heap; if (UNEXPECTED(use_custom_heap)) { - // Call observers first (before free) - HANDLE_OBSERVERS(free, ptr) - - // Check for actual custom handler (excluding observer bit) if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { - heap->custom_heap._free(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); - } else { - // No custom handler, use default heap - zend_mm_free_heap(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + zend_mm_free_custom(heap, use_custom_heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + return; } + HANDLE_OBSERVERS(free, ptr) + zend_mm_free_heap(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); return; } #endif @@ -2891,17 +2970,12 @@ ZEND_API void* ZEND_FASTCALL _erealloc(void *ptr, size_t size ZEND_FILE_LINE_DC if (UNEXPECTED(use_custom_heap)) { void *new_ptr; - // Check for actual custom handler (excluding observer bit) if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { new_ptr = heap->custom_heap._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } else { - // No custom handler, use default heap new_ptr = zend_mm_realloc_heap(heap, ptr, size, 0, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } - - // Call observers if present HANDLE_OBSERVERS(realloc, ptr, size, new_ptr) - return new_ptr; } #endif @@ -2917,17 +2991,12 @@ ZEND_API void* ZEND_FASTCALL _erealloc2(void *ptr, size_t size, size_t copy_size if (UNEXPECTED(use_custom_heap)) { void *new_ptr; - // Check for actual custom handler (excluding observer bit) if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) { new_ptr = heap->custom_heap._realloc(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } else { - // No custom handler, use default heap new_ptr = zend_mm_realloc_heap(heap, ptr, size, 1, copy_size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } - - // Call observers if present HANDLE_OBSERVERS(realloc, ptr, size, new_ptr) - return new_ptr; } #endif @@ -3443,7 +3512,6 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals) #ifdef ZTS static void alloc_globals_dtor(zend_alloc_globals *alloc_globals) { - zend_mm_observers_shutdown(alloc_globals->mm_heap); zend_mm_shutdown(alloc_globals->mm_heap, 1, 1); } #endif @@ -3645,7 +3713,6 @@ ZEND_API bool zend_mm_observer_unregister(zend_mm_heap *heap, zend_mm_observer * } pefree(current, 1); - // Update flag if no more observers if (heap->observers == NULL) { heap->use_custom_heap &= ~ZEND_MM_CUSTOM_HEAP_OBSERVED; } @@ -3658,29 +3725,6 @@ ZEND_API bool zend_mm_observer_unregister(zend_mm_heap *heap, zend_mm_observer * return false; } -void zend_mm_observers_shutdown(zend_mm_heap *heap) -{ -#if ZEND_MM_CUSTOM - if (heap == NULL) { - heap = AG(mm_heap); - if (heap == NULL) { - return; - } - } - - zend_mm_observer *current = heap->observers; - zend_mm_observer *next = NULL; - - while (current != NULL) { - next = current->next; - pefree(current, 1); - current = next; - } - - heap->observers = NULL; - heap->use_custom_heap &= ~ZEND_MM_CUSTOM_HEAP_OBSERVED; -#endif -} ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap) { #if ZEND_MM_STORAGE @@ -3745,6 +3789,7 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void #endif #if ZEND_MM_CUSTOM heap->use_custom_heap = 0; + heap->observers = NULL; #endif heap->storage = &tmp_storage; heap->huge_list = NULL; diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index d90ec4c89cf5..62c020729272 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -297,7 +297,6 @@ ZEND_API void zend_mm_get_custom_handlers_ex(zend_mm_heap *heap, typedef struct _zend_mm_observer zend_mm_observer; -// thread local ZEND_API bool zend_mm_is_observed(zend_mm_heap *heap); ZEND_API zend_mm_observer* zend_mm_observer_register( zend_mm_heap *heap, @@ -308,14 +307,6 @@ ZEND_API zend_mm_observer* zend_mm_observer_register( void (*shutdown)(bool full, bool silent) ); ZEND_API bool zend_mm_observer_unregister(zend_mm_heap *heap, zend_mm_observer *observer); -void zend_mm_observers_shutdown(zend_mm_heap *heap); - -#if ZEND_DEBUG -ZEND_API void zend_mm_set_custom_debug_handlers(zend_mm_heap *heap, - void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)); -#endif typedef struct _zend_mm_storage zend_mm_storage; diff --git a/ext/zend_test/zend_mm_observer.c b/ext/zend_test/zend_mm_observer.c index 75d63c676887..774f6d769b3d 100644 --- a/ext/zend_test/zend_mm_observer.c +++ b/ext/zend_test/zend_mm_observer.c @@ -71,8 +71,8 @@ static PHP_INI_MH(OnUpdateZendTestMMObserverEnabled) int int_value = zend_ini_parse_bool(new_value); - // Only toggle observer during runtime (ini_set during active request) - // RINIT/RSHUTDOWN handle initialization and cleanup + /* Only toggle observer during runtime (ini_set during active request). + * RINIT/RSHUTDOWN handle initialization and cleanup. */ if (stage == PHP_INI_STAGE_RUNTIME) { if (int_value == 1) { if (ZT_G(observer) == NULL) {