Skip to content

Commit 3b75f07

Browse files
authored
Stop copying internal functions into each thread (#10517)
* Stop copying internal functions into each thread It seems we don't copy internal methods for a long time, so this shouldn't be a problem. We had to copy functions in PHP-5 times, but it seems we just forgot to remove this. It's possible that some third-part extensions (e.g. profilers, tracers, debuggers) modify internal functions. After this change that may cause race conditions in ZTS build (but we already jave the same behavior for internal methods). Observer API should provide necesssary functionality to avoid shared structures modification. * Remove unused function
1 parent 0ebef33 commit 3b75f07

File tree

2 files changed

+20
-64
lines changed

2 files changed

+20
-64
lines changed

Zend/zend.c

+17-64
Original file line numberDiff line numberDiff line change
@@ -674,69 +674,6 @@ static void auto_global_dtor(zval *zv) /* {{{ */
674674
/* }}} */
675675

676676
#ifdef ZTS
677-
static void function_copy_ctor(zval *zv) /* {{{ */
678-
{
679-
zend_function *old_func = Z_FUNC_P(zv);
680-
zend_function *func;
681-
682-
if (old_func->type == ZEND_USER_FUNCTION) {
683-
ZEND_ASSERT(old_func->op_array.fn_flags & ZEND_ACC_IMMUTABLE);
684-
return;
685-
}
686-
func = pemalloc(sizeof(zend_internal_function), 1);
687-
Z_FUNC_P(zv) = func;
688-
memcpy(func, old_func, sizeof(zend_internal_function));
689-
function_add_ref(func);
690-
if ((old_func->common.fn_flags & (ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_HAS_TYPE_HINTS))
691-
&& old_func->common.arg_info) {
692-
uint32_t i;
693-
uint32_t num_args = old_func->common.num_args + 1;
694-
zend_arg_info *arg_info = old_func->common.arg_info - 1;
695-
zend_arg_info *new_arg_info;
696-
697-
if (old_func->common.fn_flags & ZEND_ACC_VARIADIC) {
698-
num_args++;
699-
}
700-
new_arg_info = pemalloc(sizeof(zend_arg_info) * num_args, 1);
701-
memcpy(new_arg_info, arg_info, sizeof(zend_arg_info) * num_args);
702-
for (i = 0 ; i < num_args; i++) {
703-
if (ZEND_TYPE_HAS_LIST(arg_info[i].type)) {
704-
zend_type_list *old_list = ZEND_TYPE_LIST(arg_info[i].type);
705-
zend_type_list *new_list = pemalloc(ZEND_TYPE_LIST_SIZE(old_list->num_types), 1);
706-
memcpy(new_list, old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types));
707-
ZEND_TYPE_SET_PTR(new_arg_info[i].type, new_list);
708-
709-
zend_type *list_type;
710-
ZEND_TYPE_LIST_FOREACH(new_list, list_type) {
711-
zend_string *name = zend_string_dup(ZEND_TYPE_NAME(*list_type), 1);
712-
ZEND_TYPE_SET_PTR(*list_type, name);
713-
} ZEND_TYPE_LIST_FOREACH_END();
714-
} else if (ZEND_TYPE_HAS_NAME(arg_info[i].type)) {
715-
zend_string *name = zend_string_dup(ZEND_TYPE_NAME(arg_info[i].type), 1);
716-
ZEND_TYPE_SET_PTR(new_arg_info[i].type, name);
717-
}
718-
}
719-
func->common.arg_info = new_arg_info + 1;
720-
}
721-
if (old_func->common.attributes) {
722-
zend_attribute *old_attr;
723-
724-
func->common.attributes = NULL;
725-
726-
ZEND_HASH_PACKED_FOREACH_PTR(old_func->common.attributes, old_attr) {
727-
uint32_t i;
728-
zend_attribute *attr;
729-
730-
attr = zend_add_attribute(&func->common.attributes, old_attr->name, old_attr->argc, old_attr->flags, old_attr->offset, old_attr->lineno);
731-
732-
for (i = 0 ; i < old_attr->argc; i++) {
733-
ZVAL_DUP(&attr->args[i].value, &old_attr->args[i].value);
734-
}
735-
} ZEND_HASH_FOREACH_END();
736-
}
737-
}
738-
/* }}} */
739-
740677
static void auto_global_copy_ctor(zval *zv) /* {{{ */
741678
{
742679
zend_auto_global *old_ag = (zend_auto_global *) Z_PTR_P(zv);
@@ -756,7 +693,8 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{
756693

757694
compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable));
758695
zend_hash_init(compiler_globals->function_table, 1024, NULL, ZEND_FUNCTION_DTOR, 1);
759-
zend_hash_copy(compiler_globals->function_table, global_function_table, function_copy_ctor);
696+
zend_hash_copy(compiler_globals->function_table, global_function_table, NULL);
697+
compiler_globals->copied_functions_count = zend_hash_num_elements(compiler_globals->function_table);
760698

761699
compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable));
762700
zend_hash_init(compiler_globals->class_table, 64, NULL, ZEND_CLASS_DTOR, 1);
@@ -790,6 +728,21 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals) /* {{
790728
static void compiler_globals_dtor(zend_compiler_globals *compiler_globals) /* {{{ */
791729
{
792730
if (compiler_globals->function_table != GLOBAL_FUNCTION_TABLE) {
731+
uint32_t n = compiler_globals->copied_functions_count;
732+
733+
/* Prevent destruction of functions copied from the main process context */
734+
if (zend_hash_num_elements(compiler_globals->function_table) <= n) {
735+
compiler_globals->function_table->nNumUsed = 0;
736+
} else {
737+
Bucket *p = compiler_globals->function_table->arData;
738+
739+
compiler_globals->function_table->nNumOfElements -= n;
740+
while (n != 0) {
741+
ZVAL_UNDEF(&p->val);
742+
p++;
743+
n--;
744+
}
745+
}
793746
zend_hash_destroy(compiler_globals->function_table);
794747
free(compiler_globals->function_table);
795748
}

Zend/zend_globals.h

+3
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ struct _zend_compiler_globals {
144144
uint32_t rtd_key_counter;
145145

146146
zend_stack short_circuiting_opnums;
147+
#ifdef ZTS
148+
uint32_t copied_functions_count;
149+
#endif
147150
};
148151

149152

0 commit comments

Comments
 (0)