summaryrefslogtreecommitdiff
path: root/sapi
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-05-18 15:46:06 +0200
committerNikita Popov <nikita.ppv@gmail.com>2021-03-01 11:35:54 +0100
commit47a2e5c785cdba71e003d9ad77cb799d4be88806 (patch)
treed03767c644d6d6652a882b2b2946ff55a7a036a9 /sapi
parentb86dfb0e747a2254f3de97347ac89d791572141e (diff)
downloadphp-git-47a2e5c785cdba71e003d9ad77cb799d4be88806.tar.gz
Reference dynamic functions through dynamic_defs
Currently, dynamically declared functions and closures are inserted into the function table under a runtime definition key, and then later possibly renamed. When opcache is not used and a file containing a closure is repeatedly included, this leads to a very large memory leak, as the no longer needed closure declarations will never be freed (https://bugs.php.net/bug.php?id=76982). With this patch, dynamic functions are instead stored in a dynamic_func_defs member on the op_array, which opcodes reference by index. When the parent op_array is destroyed, the dynamic_func_defs it contains are also destroyed (unless they are stilled used elsewhere, e.g. because they have been bound, or are used by a live closure). This resolves the fundamental part of the leak, though doesn't completely fix it yet due to some arena allocations. The main non-obvious change here is to static variable handling: We can't destroy static_variables_ptr in destroy_op_array, as e.g. that would clear the static variables in a dynamic function when the op_array containing it is destroyed. Static variable destruction is separated out for this reason (we already do static variable destruction separately for normal functions, so we only need to handle main scripts). Closes GH-5595.
Diffstat (limited to 'sapi')
-rw-r--r--sapi/phpdbg/phpdbg_print.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/sapi/phpdbg/phpdbg_print.c b/sapi/phpdbg/phpdbg_print.c
index e3bbb9fed8..e009432a9e 100644
--- a/sapi/phpdbg/phpdbg_print.c
+++ b/sapi/phpdbg/phpdbg_print.c
@@ -87,6 +87,13 @@ static inline void phpdbg_print_function_helper(zend_function *method) /* {{{ */
efree(decode);
opline++;
} while (opcode++ < end);
+
+ for (uint32_t i = 0; i < op_array->num_dynamic_func_defs; i++) {
+ zend_op_array *def = op_array->dynamic_func_defs[i];
+ phpdbg_out("\ndynamic def: %i, function name: %.*s\n",
+ i, (int) ZSTR_LEN(def->function_name), ZSTR_VAL(def->function_name));
+ phpdbg_print_function_helper((zend_function *) def);
+ }
}
} break;