Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0366f30

Browse files
add gc and shutdown callbacks
1 parent fd47cd8 commit 0366f30

File tree

10 files changed

+236
-15
lines changed

10 files changed

+236
-15
lines changed

‎Zend/zend_alloc.c‎

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#include "zend_multiply.h"
5959
#include "zend_bitset.h"
6060
#include "zend_mmap.h"
61+
#include "zend_portability.h"
6162
#include <signal.h>
6263

6364
#ifdef HAVE_UNISTD_H
@@ -273,11 +274,15 @@ struct _zend_mm_heap {
273274
void *(*_malloc)(size_t);
274275
void (*_free)(void*);
275276
void *(*_realloc)(void*, size_t);
277+
size_t (*_gc)(void);
278+
void (*_shutdown)(bool full, bool silent);
276279
} std;
277280
struct {
278281
void *(*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
279282
void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
280283
void *(*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
284+
size_t (*_gc)(void ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
285+
void (*_shutdown)(bool full, bool silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
281286
} debug;
282287
} custom_heap;
283288
HashTable *tracked_allocs;
@@ -1968,6 +1973,10 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap)
19681973

19691974
#if ZEND_MM_CUSTOM
19701975
if (heap->use_custom_heap) {
1976+
size_t (*gc)(void) = heap->custom_heap.std._gc;
1977+
if (gc) {
1978+
return gc();
1979+
}
19711980
return 0;
19721981
}
19731982
#endif
@@ -2265,7 +2274,7 @@ static void *tracked_malloc(size_t size);
22652274
static void tracked_free_all(void);
22662275
#endif
22672276

2268-
void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
2277+
ZEND_APIvoid zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
22692278
{
22702279
zend_mm_chunk *p;
22712280
zend_mm_huge_list *list;
@@ -2293,6 +2302,10 @@ void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
22932302
heap->custom_heap.std._free(heap);
22942303
}
22952304
}
2305+
void (*shutdown)(bool, bool) = heap->custom_heap.std._shutdown;
2306+
if (shutdown) {
2307+
shutdown(full, silent);
2308+
}
22962309
return;
22972310
}
22982311
#endif
@@ -2980,6 +2993,16 @@ ZEND_API zend_mm_heap *zend_mm_get_heap(void)
29802993
return AG(mm_heap);
29812994
}
29822995

2996+
ZEND_API zend_mm_heap *zend_mm_heap_create(void)
2997+
{
2998+
return zend_mm_init();
2999+
}
3000+
3001+
ZEND_API void zend_mm_heap_free(zend_mm_heap *heap)
3002+
{
3003+
zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE);
3004+
}
3005+
29833006
ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap)
29843007
{
29853008
#if ZEND_MM_CUSTOM
@@ -2990,9 +3013,11 @@ ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap)
29903013
}
29913014

29923015
ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
2993-
void* (*_malloc)(size_t),
2994-
void (*_free)(void*),
2995-
void* (*_realloc)(void*, size_t))
3016+
void* (*_malloc)(size_t),
3017+
void (*_free)(void*),
3018+
void* (*_realloc)(void*, size_t),
3019+
size_t (*_gc)(void),
3020+
void (*_shutdown)(bool, bool))
29963021
{
29973022
#if ZEND_MM_CUSTOM
29983023
zend_mm_heap *_heap = (zend_mm_heap*)heap;
@@ -3004,14 +3029,18 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
30043029
_heap->custom_heap.std._malloc = _malloc;
30053030
_heap->custom_heap.std._free = _free;
30063031
_heap->custom_heap.std._realloc = _realloc;
3032+
_heap->custom_heap.std._gc = _gc;
3033+
_heap->custom_heap.std._shutdown = _shutdown;
30073034
}
30083035
#endif
30093036
}
30103037

30113038
ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
3012-
void* (**_malloc)(size_t),
3013-
void (**_free)(void*),
3014-
void* (**_realloc)(void*, size_t))
3039+
void* (**_malloc)(size_t),
3040+
void (**_free)(void*),
3041+
void* (**_realloc)(void*, size_t),
3042+
size_t (**_gc)(void),
3043+
void (**_shutdown)(bool, bool))
30153044
{
30163045
#if ZEND_MM_CUSTOM
30173046
zend_mm_heap *_heap = (zend_mm_heap*)heap;
@@ -3020,15 +3049,21 @@ ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
30203049
*_malloc = _heap->custom_heap.std._malloc;
30213050
*_free = _heap->custom_heap.std._free;
30223051
*_realloc = _heap->custom_heap.std._realloc;
3052+
*_gc = _heap->custom_heap.std._gc;
3053+
*_shutdown = _heap->custom_heap.std._shutdown;
30233054
} else {
30243055
*_malloc = NULL;
30253056
*_free = NULL;
30263057
*_realloc = NULL;
3058+
*_gc = NULL;
3059+
*_shutdown = NULL;
30273060
}
30283061
#else
30293062
*_malloc = NULL;
30303063
*_free = NULL;
30313064
*_realloc = NULL;
3065+
*_gc = NULL;
3066+
*_shutdown = NULL;
30323067
#endif
30333068
}
30343069

‎Zend/zend_alloc.h‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ ZEND_API size_t ZEND_FASTCALL _zend_mm_block_size(zend_mm_heap *heap, void *p ZE
261261
#define zend_mm_realloc2_rel(heap, p, size, copy_size) _zend_mm_realloc2((heap), (p), (size), (copy_size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
262262
#define zend_mm_block_size_rel(heap, p) _zend_mm_block_size((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
263263

264+
ZEND_API zend_mm_heap *zend_mm_heap_create(void);
265+
ZEND_API void zend_mm_heap_free(zend_mm_heap* heap);
264266
ZEND_API zend_mm_heap *zend_mm_set_heap(zend_mm_heap *new_heap);
265267
ZEND_API zend_mm_heap *zend_mm_get_heap(void);
266268

@@ -274,11 +276,15 @@ ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap);
274276
ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
275277
void* (*_malloc)(size_t),
276278
void (*_free)(void*),
277-
void* (*_realloc)(void*, size_t));
279+
void* (*_realloc)(void*, size_t),
280+
size_t (*gc)(void),
281+
void (*shutdown)(bool full, bool silent));
278282
ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
279283
void* (**_malloc)(size_t),
280284
void (**_free)(void*),
281-
void* (**_realloc)(void*, size_t));
285+
void* (**_realloc)(void*, size_t),
286+
size_t (**gc)(void),
287+
void (**shutdown)(bool full, bool silent));
282288

283289
#if ZEND_DEBUG
284290
ZEND_API void zend_mm_set_custom_debug_handlers(zend_mm_heap *heap,

‎ext/zend_test/config.m4‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ PHP_ARG_ENABLE([zend-test],
44
[Enable zend_test extension])])
55

66
if test "$PHP_ZEND_TEST" != "no"; then
7-
PHP_NEW_EXTENSION(zend_test, test.c observer.c fiber.c iterators.c object_handlers.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
7+
PHP_NEW_EXTENSION(zend_test, test.c observer.c fiber.c iterators.c object_handlers.c zend_mm_custom_handlers.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
88
fi

‎ext/zend_test/config.w32‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
ARG_ENABLE("zend-test", "enable zend_test extension", "no");
44

55
if (PHP_ZEND_TEST != "no") {
6-
EXTENSION("zend_test", "test.c observer.c fiber.c iterators.c object_handlers.c", PHP_ZEND_TEST_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
6+
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");
77
ADD_FLAG("CFLAGS_ZEND_TEST", "/D PHP_ZEND_TEST_EXPORTS ");
88
}

‎ext/zend_test/php_test.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
6262
zend_long quantity_value;
6363
zend_string *str_test;
6464
zend_string *not_empty_str_test;
65+
int zend_mm_custom_handlers_enabled;
6566
ZEND_END_MODULE_GLOBALS(zend_test)
6667

6768
extern ZEND_DECLARE_MODULE_GLOBALS(zend_test)

‎ext/zend_test/test.c‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "test_arginfo.h"
3636
#include "zend_call_stack.h"
3737
#include "zend_exceptions.h"
38+
#include "zend_mm_custom_handlers.h"
3839

3940
// `php.h` sets `NDEBUG` when not `PHP_DEBUG` which will make `assert()` from
4041
// assert.h a no-op. In order to have `assert()` working on NDEBUG builds, we
@@ -682,7 +683,9 @@ static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM)
682683
ZT_G(zend_test_heap),
683684
zend_test_custom_malloc,
684685
zend_test_custom_free,
685-
zend_test_custom_realloc
686+
zend_test_custom_realloc,
687+
NULL,
688+
NULL
686689
);
687690
ZT_G(zend_orig_heap) = zend_mm_get_heap();
688691
zend_mm_set_heap(ZT_G(zend_test_heap));
@@ -994,6 +997,7 @@ PHP_INI_BEGIN()
994997
STD_PHP_INI_ENTRY("zend_test.str_test", "", PHP_INI_ALL, OnUpdateStr, str_test, zend_zend_test_globals, zend_test_globals)
995998
STD_PHP_INI_ENTRY("zend_test.not_empty_str_test", "val", PHP_INI_ALL, OnUpdateStrNotEmpty, not_empty_str_test, zend_zend_test_globals, zend_test_globals)
996999
STD_PHP_INI_BOOLEAN("zend_test.observe_opline_in_zendmm", "0", PHP_INI_ALL, OnUpdateZendTestObserveOplineInZendMM, observe_opline_in_zendmm, zend_zend_test_globals, zend_test_globals)
1000+
STD_PHP_INI_BOOLEAN("zend_test.zend_mm_custom_handlers.enabled", "0", PHP_INI_SYSTEM, OnUpdateBool, zend_mm_custom_handlers_enabled, zend_zend_test_globals, zend_test_globals)
9971001
PHP_INI_END()
9981002

9991003
void (*old_zend_execute_ex)(zend_execute_data *execute_data);
@@ -1217,11 +1221,13 @@ PHP_RINIT_FUNCTION(zend_test)
12171221
{
12181222
zend_hash_init(&ZT_G(global_weakmap), 8, NULL, ZVAL_PTR_DTOR, 0);
12191223
ZT_G(observer_nesting_depth) = 0;
1224+
zend_mm_custom_handlers_rinit();
12201225
return SUCCESS;
12211226
}
12221227

12231228
PHP_RSHUTDOWN_FUNCTION(zend_test)
12241229
{
1230+
zend_mm_custom_handlers_rshutdown();
12251231
zend_ulong obj_key;
12261232
ZEND_HASH_FOREACH_NUM_KEY(&ZT_G(global_weakmap), obj_key) {
12271233
zend_weakrefs_hash_del(&ZT_G(global_weakmap), zend_weakref_key_to_object(obj_key));
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
--TEST--
2+
ZendMM Custom Handlers: garbage collection
3+
--EXTENSIONS--
4+
zend_test
5+
--INI--
6+
zend_test.zend_mm_custom_handlers.enabled=1
7+
opcache.enable=0
8+
--FILE--
9+
<?php
10+
gc_mem_caches();
11+
?>
12+
--EXPECTREGEX--
13+
.*ZendMM GC freed \d+ bytes.*
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| https://www.php.net/license/3_01.txt |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| license@php.net so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Author: Florian Engelhardt <florian@engelhardt.tc> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#include "php.h"
18+
#include "php_test.h"
19+
#include "ext/standard/info.h"
20+
#include "ext/standard/php_var.h"
21+
#include "Zend/zend_alloc.h"
22+
#include <stddef.h>
23+
#include <stdio.h>
24+
25+
// the previous heap that was found in ZendMM
26+
zend_mm_heap* prev_heap = NULL;
27+
28+
// the custom handlers that might have been found in the previous heap in case
29+
// there are any
30+
void* (*custom_malloc)(size_t) = NULL;
31+
void (*custom_free)(void*) = NULL;
32+
void* (*custom_realloc)(void *, size_t) = NULL;
33+
size_t (*custom_gc)(void) = NULL;
34+
void (*custom_shutdown)(bool, bool) = NULL;
35+
36+
// this is our heap that we install our custom handlers on and inject into
37+
// ZendMM
38+
zend_mm_heap* heap = NULL;
39+
40+
void* observe_malloc(size_t size)
41+
{
42+
void *ptr = NULL;
43+
if (custom_malloc) {
44+
ptr = custom_malloc(size);
45+
} else {
46+
ptr = _zend_mm_alloc(prev_heap, size ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
47+
}
48+
printf("Allocated %zu bytes at %p\n", size, ptr);
49+
return ptr;
50+
}
51+
52+
void observe_free(void* ptr)
53+
{
54+
if (custom_free)
55+
{
56+
custom_free(ptr);
57+
} else {
58+
_zend_mm_free(prev_heap, ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
59+
}
60+
printf("Freed memory at %p\n", ptr);
61+
}
62+
63+
void* observe_realloc(void* ptr, size_t size)
64+
{
65+
void * new_ptr;
66+
if (custom_realloc)
67+
{
68+
new_ptr = custom_realloc(ptr, size);
69+
} else {
70+
new_ptr = _zend_mm_realloc(prev_heap, ptr, size ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
71+
}
72+
printf("Realloc of %zu bytes from %p to %p\n", size, ptr, new_ptr);
73+
return new_ptr;
74+
}
75+
76+
size_t observe_gc(void)
77+
{
78+
size_t size = 0;
79+
if (custom_gc) {
80+
size = custom_gc();
81+
} else {
82+
size = zend_mm_gc(prev_heap);
83+
}
84+
printf("ZendMM GC freed %zu bytes", size);
85+
return size;
86+
}
87+
88+
void observe_shutdown(bool full, bool silent)
89+
{
90+
if (custom_shutdown) {
91+
custom_shutdown(full, silent);
92+
} else {
93+
zend_mm_shutdown(prev_heap, full, silent);
94+
}
95+
printf("Shutdown happened: full -> %d, silent -> %d\n", full, silent);
96+
}
97+
98+
void zend_mm_custom_handlers_rinit(void)
99+
{
100+
if (ZT_G(zend_mm_custom_handlers_enabled) == 0) {
101+
return;
102+
}
103+
prev_heap = zend_mm_get_heap();
104+
if (zend_mm_is_custom_heap(prev_heap)) {
105+
zend_mm_get_custom_handlers(
106+
prev_heap,
107+
&custom_malloc,
108+
&custom_free,
109+
&custom_realloc,
110+
&custom_gc,
111+
&custom_shutdown
112+
);
113+
}
114+
printf("Prev handlers at %p, %p, %p, %p, %p\n", custom_malloc, custom_free, custom_realloc, custom_gc, custom_shutdown);
115+
heap = zend_mm_heap_create();
116+
zend_mm_set_custom_handlers(
117+
heap,
118+
observe_malloc,
119+
observe_free,
120+
observe_realloc,
121+
observe_gc,
122+
observe_shutdown
123+
);
124+
zend_mm_set_heap(heap);
125+
printf("Heap at %p installed in ZendMM (orig at %p)\n", heap, prev_heap);
126+
}
127+
128+
void zend_mm_custom_handlers_rshutdown(void)
129+
{
130+
if (ZT_G(zend_mm_custom_handlers_enabled) == 0) {
131+
return;
132+
}
133+
zend_mm_set_heap(prev_heap);
134+
zend_mm_heap_free(heap);
135+
heap = NULL;
136+
printf("Prev heap at %p restored in ZendMM\n", prev_heap);
137+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| https://www.php.net/license/3_01.txt |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| license@php.net so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Author: Florian Engelhardt <florian@engelhardt.tc> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#ifndef ZEND_TEST_MM_CUSTOM_HANDLERS_H
18+
#define ZEND_TEST_MM_CUSTOM_HANDLERS_H
19+
20+
void zend_mm_custom_handlers_rinit(void);
21+
void zend_mm_custom_handlers_rshutdown(void);
22+
23+
#endif

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /