Skip to content

Proposing ZendMM Observer API #11758

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c3e9a90
Add ZendMM observer
realFlowControl Jul 5, 2023
2932fd6
remove `php.h`
realFlowControl Jul 24, 2023
1059203
Add missing `ZEND_API`
realFlowControl Jul 24, 2023
267866a
extract `zend_mm_observer_find_heap_observer`
realFlowControl Jul 24, 2023
793003f
make observer less complex
realFlowControl Jul 25, 2023
f8b0601
fix comments and code style
realFlowControl Jul 25, 2023
0759afc
shutdown ZendMM observers during request shutdown
realFlowControl Jul 25, 2023
55b81ab
small cleanup
realFlowControl Jul 26, 2023
fecacac
cleanup unregister
realFlowControl Jul 27, 2023
88fbb2c
add tests for ZendMM Observer
realFlowControl Jul 26, 2023
4d74192
rename zendmm -> zend_mm
realFlowControl Jul 28, 2023
c74e50a
removed unused functions
realFlowControl Jul 28, 2023
dc2a07d
add missing author
realFlowControl Jul 28, 2023
3167fff
remove bad practice comment
realFlowControl Jul 28, 2023
d11819a
fix naming and bool parsing
realFlowControl Jul 28, 2023
a7ea288
make functions static to avoid name clashes
realFlowControl Jul 28, 2023
2256cf7
simplyfy test
realFlowControl Jul 28, 2023
e5d60dd
deduplicate observer calling
realFlowControl Jul 28, 2023
d961282
Add parameter names
realFlowControl Jul 31, 2023
a3c4a15
fix test
realFlowControl Jul 31, 2023
b3d5b5a
fix tests on windows
realFlowControl Aug 1, 2023
1a3a797
fix asan tests
realFlowControl Aug 2, 2023
b5729da
remove `is_zend_mm()` check
realFlowControl Aug 3, 2023
10cba17
Add missing author
realFlowControl Aug 3, 2023
70bdf69
observe ZendMM garbage collection
realFlowControl Oct 27, 2023
8fa36be
Add shutdown observer and fix debug builds
realFlowControl Oct 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Add shutdown observer and fix debug builds
  • Loading branch information
realFlowControl committed Feb 15, 2024
commit 8fa36be1f0abed033142de503cb7e1d8efe405de
38 changes: 28 additions & 10 deletions Zend/zend_alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,23 @@ 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 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_OBSERVERS(heap, use_custom_heap, observer_function, ...) \
#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) { \
Expand Down Expand Up @@ -1989,7 +2001,7 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap)
#if ZEND_MM_CUSTOM
int use_custom_heap = heap->use_custom_heap;
if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) {
HANDLE_OBSERVERS(heap, use_custom_heap, gc ,0);
HANDLE_NO_DEBUG_OBSERVERS(gc ,0);
return 0;
}
#endif
Expand Down Expand Up @@ -2089,7 +2101,7 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap)
} while (chunk != heap->main_chunk);

#if ZEND_MM_CUSTOM
HANDLE_OBSERVERS(heap, use_custom_heap, gc, collected * ZEND_MM_PAGE_SIZE);
HANDLE_NO_DEBUG_OBSERVERS(gc, collected * ZEND_MM_PAGE_SIZE);
#endif

return collected * ZEND_MM_PAGE_SIZE;
Expand Down Expand Up @@ -2297,8 +2309,12 @@ void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
zend_mm_huge_list *list;

#if ZEND_MM_CUSTOM
int use_custom_heap = heap->use_custom_heap;

HANDLE_NO_DEBUG_OBSERVERS(shutdown, full, silent)
zend_mm_observers_shutdown(heap);
if (heap->use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) {

if (use_custom_heap & ~ZEND_MM_CUSTOM_HEAP_OBSERVED) {
if (heap->custom_heap.std._malloc == tracked_malloc) {
if (silent) {
tracked_free_all();
Expand All @@ -2314,7 +2330,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
}

if (full) {
if (ZEND_DEBUG && heap->use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) {
if (ZEND_DEBUG && use_custom_heap & ZEND_MM_CUSTOM_HEAP_DEBUG) {
heap->custom_heap.debug._free(heap ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
} else {
heap->custom_heap.std._free(heap);
Expand Down Expand Up @@ -2534,7 +2550,7 @@ static ZEND_COLD void* ZEND_FASTCALL _malloc_custom(size_t size ZEND_FILE_LINE_D
// 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(heap, use_custom_heap, malloc, size, ptr)
HANDLE_OBSERVERS(malloc, size, ptr)
return ptr;
}

Expand All @@ -2543,7 +2559,7 @@ static ZEND_COLD void ZEND_FASTCALL _efree_custom(void *ptr ZEND_FILE_LINE_DC ZE
zend_mm_heap *heap = AG(mm_heap);
int use_custom_heap = heap->use_custom_heap;

HANDLE_OBSERVERS(heap, use_custom_heap, free, ptr)
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);
Expand All @@ -2568,7 +2584,7 @@ static ZEND_COLD void* ZEND_FASTCALL _realloc_custom(void *ptr, size_t size ZEND
// 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(heap, use_custom_heap, realloc, ptr, size, new_ptr)
HANDLE_OBSERVERS(realloc, ptr, size, new_ptr)
return new_ptr;
}
#endif
Expand Down Expand Up @@ -3108,7 +3124,8 @@ ZEND_API zend_mm_observer* zend_mm_observer_register(
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 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) {
Expand All @@ -3121,6 +3138,7 @@ ZEND_API zend_mm_observer* zend_mm_observer_register(
node->free = free;
node->realloc = realloc;
node->gc = gc;
node->shutdown = shutdown;
node->next = NULL;

// set bitflag for observers being around
Expand Down
3 changes: 2 additions & 1 deletion Zend/zend_alloc.h
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the ZEND_API parts of this file should be moved to Zend/observer.h?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, there is already a Zend/zend_observer.h file, but this is for the Zend Engine. I think this could lead to misunderstandings. Personally I am totally okay with having this in Zend/zend_alloc.h as everything regarding the ZendMM is there. We might consider moving it to a Zend/zend_alloc_observer.h file to keep the naming clear.
Personally I would leave it as is, but I do not have any hard feelings the one way or the other.

Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,8 @@ ZEND_API zend_mm_observer* zend_mm_observer_register(
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 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);
Expand Down
12 changes: 12 additions & 0 deletions ext/zend_test/tests/zend_mm_observer_shutdown_01.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--TEST--
ZendMM Observer: Observe shutdown
--EXTENSIONS--
zend_test
--INI--
zend_test.zend_mm_observer.enabled=1
--FILE--
<?php
echo "done.";
?>
--EXPECTREGEX--
.*shutdown in progress: full\(0\), silent\(1\).*
25 changes: 16 additions & 9 deletions ext/zend_test/zend_mm_observer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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 {
Expand Down Expand Up @@ -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);
Expand All @@ -121,4 +129,3 @@ void zend_test_mm_observer_rshutdown(void)
}
ZT_G(observer) = NULL;
}