mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Add tracked allocator mode
In this case we will use the system allocator, but still remember all allocations and free them the same way that Zend MM does. This allows us to accurately model leak behavior. Enabled using USE_ZEND_ALLOC=0 USE_TRACKED_ALLOC=1.
This commit is contained in:
parent
218c18530a
commit
cfeda978df
1 changed files with 71 additions and 11 deletions
|
@ -266,6 +266,7 @@ struct _zend_mm_heap {
|
||||||
void *(*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
|
void *(*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
|
||||||
} debug;
|
} debug;
|
||||||
} custom_heap;
|
} custom_heap;
|
||||||
|
HashTable *tracked_allocs;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2182,6 +2183,11 @@ static void zend_mm_check_leaks(zend_mm_heap *heap)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ZEND_MM_CUSTOM
|
||||||
|
static void *tracked_malloc(size_t size);
|
||||||
|
static void tracked_free_all();
|
||||||
|
#endif
|
||||||
|
|
||||||
void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent)
|
void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent)
|
||||||
{
|
{
|
||||||
zend_mm_chunk *p;
|
zend_mm_chunk *p;
|
||||||
|
@ -2189,12 +2195,19 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent)
|
||||||
|
|
||||||
#if ZEND_MM_CUSTOM
|
#if ZEND_MM_CUSTOM
|
||||||
if (heap->use_custom_heap) {
|
if (heap->use_custom_heap) {
|
||||||
if (full) {
|
if (heap->custom_heap.std._malloc == tracked_malloc) {
|
||||||
if (ZEND_DEBUG && heap->use_custom_heap == ZEND_MM_CUSTOM_HEAP_DEBUG) {
|
if (silent) {
|
||||||
heap->custom_heap.debug._free(heap ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
|
tracked_free_all();
|
||||||
} else {
|
|
||||||
heap->custom_heap.std._free(heap);
|
|
||||||
}
|
}
|
||||||
|
zend_hash_clean(heap->tracked_allocs);
|
||||||
|
if (full) {
|
||||||
|
zend_hash_destroy(heap->tracked_allocs);
|
||||||
|
free(heap->tracked_allocs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (full) {
|
||||||
|
free(heap);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2661,6 +2674,42 @@ ZEND_API void shutdown_memory_manager(int silent, int full_shutdown)
|
||||||
zend_mm_shutdown(AG(mm_heap), full_shutdown, silent);
|
zend_mm_shutdown(AG(mm_heap), full_shutdown, silent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ZEND_MM_CUSTOM
|
||||||
|
static void *tracked_malloc(size_t size)
|
||||||
|
{
|
||||||
|
void *ptr = __zend_malloc(size);
|
||||||
|
zend_ulong h = ((uintptr_t) ptr) >> ZEND_MM_ALIGNMENT_LOG2;
|
||||||
|
ZEND_ASSERT((void *) (uintptr_t) (h << ZEND_MM_ALIGNMENT_LOG2) == ptr);
|
||||||
|
zend_hash_index_add_empty_element(AG(mm_heap)->tracked_allocs, h);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tracked_free(void *ptr) {
|
||||||
|
zend_ulong h = ((uintptr_t) ptr) >> ZEND_MM_ALIGNMENT_LOG2;
|
||||||
|
zend_hash_index_del(AG(mm_heap)->tracked_allocs, h);
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *tracked_realloc(void *ptr, size_t new_size) {
|
||||||
|
zend_ulong h = ((uintptr_t) ptr) >> ZEND_MM_ALIGNMENT_LOG2;
|
||||||
|
zend_hash_index_del(AG(mm_heap)->tracked_allocs, h);
|
||||||
|
ptr = __zend_realloc(ptr, new_size);
|
||||||
|
h = ((uintptr_t) ptr) >> ZEND_MM_ALIGNMENT_LOG2;
|
||||||
|
ZEND_ASSERT((void *) (uintptr_t) (h << ZEND_MM_ALIGNMENT_LOG2) == ptr);
|
||||||
|
zend_hash_index_add_empty_element(AG(mm_heap)->tracked_allocs, h);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tracked_free_all() {
|
||||||
|
HashTable *tracked_allocs = AG(mm_heap)->tracked_allocs;
|
||||||
|
zend_ulong h;
|
||||||
|
ZEND_HASH_FOREACH_NUM_KEY(tracked_allocs, h) {
|
||||||
|
void *ptr = (void *) (uintptr_t) (h << ZEND_MM_ALIGNMENT_LOG2);
|
||||||
|
free(ptr);
|
||||||
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void alloc_globals_ctor(zend_alloc_globals *alloc_globals)
|
static void alloc_globals_ctor(zend_alloc_globals *alloc_globals)
|
||||||
{
|
{
|
||||||
char *tmp;
|
char *tmp;
|
||||||
|
@ -2668,12 +2717,23 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals)
|
||||||
#if ZEND_MM_CUSTOM
|
#if ZEND_MM_CUSTOM
|
||||||
tmp = getenv("USE_ZEND_ALLOC");
|
tmp = getenv("USE_ZEND_ALLOC");
|
||||||
if (tmp && !zend_atoi(tmp, 0)) {
|
if (tmp && !zend_atoi(tmp, 0)) {
|
||||||
alloc_globals->mm_heap = malloc(sizeof(zend_mm_heap));
|
zend_bool tracked = (tmp = getenv("USE_TRACKED_ALLOC")) && zend_atoi(tmp, 0);
|
||||||
memset(alloc_globals->mm_heap, 0, sizeof(zend_mm_heap));
|
zend_mm_heap *mm_heap = alloc_globals->mm_heap = malloc(sizeof(zend_mm_heap));
|
||||||
alloc_globals->mm_heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_STD;
|
memset(mm_heap, 0, sizeof(zend_mm_heap));
|
||||||
alloc_globals->mm_heap->custom_heap.std._malloc = __zend_malloc;
|
mm_heap->use_custom_heap = ZEND_MM_CUSTOM_HEAP_STD;
|
||||||
alloc_globals->mm_heap->custom_heap.std._free = free;
|
if (!tracked) {
|
||||||
alloc_globals->mm_heap->custom_heap.std._realloc = __zend_realloc;
|
/* Use system allocator. */
|
||||||
|
mm_heap->custom_heap.std._malloc = __zend_malloc;
|
||||||
|
mm_heap->custom_heap.std._free = free;
|
||||||
|
mm_heap->custom_heap.std._realloc = __zend_realloc;
|
||||||
|
} else {
|
||||||
|
/* Use system allocator and track allocations for auto-free. */
|
||||||
|
mm_heap->custom_heap.std._malloc = tracked_malloc;
|
||||||
|
mm_heap->custom_heap.std._free = tracked_free;
|
||||||
|
mm_heap->custom_heap.std._realloc = tracked_realloc;
|
||||||
|
mm_heap->tracked_allocs = malloc(sizeof(HashTable));
|
||||||
|
zend_hash_init(mm_heap->tracked_allocs, 1024, NULL, NULL, 1);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue