From: Dmitry Stogov Date: Mon, 31 Mar 2014 12:09:45 +0000 (+0400) Subject: fixed craches at request shutdown and memory leaks X-Git-Tag: POST_PHPNG_MERGE~412^2~201 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47fdb9eae33bdb36d79e6b7eb7afa87fbde9c0ed;p=php fixed craches at request shutdown and memory leaks --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 807ebd508e..9ba40dfc33 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5442,6 +5442,7 @@ void zend_do_declare_property(znode *var_name, const znode *value, zend_uint acc Z_STR(var_name->u.constant) = zend_new_interned_string(Z_STR(var_name->u.constant) TSRMLS_CC); zend_declare_property_ex(CG(active_class_entry), Z_STR(var_name->u.constant), &property, access_type, comment TSRMLS_CC); //??? efree(Z_STRVAL(var_name->u.constant)); + STR_RELEASE(Z_STR(var_name->u.constant)); } /* }}} */ diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 039c3bbd76..08108d283f 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -115,6 +115,9 @@ ZEND_API void destroy_zend_function(zend_function *function TSRMLS_DC) destroy_op_array((zend_op_array *) function TSRMLS_CC); break; case ZEND_INTERNAL_FUNCTION: + if (function->common.function_name) { + STR_RELEASE(function->common.function_name); + } /* do nothing */ break; } diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 85347be976..5df02c98c8 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -2524,9 +2524,14 @@ static void accel_globals_ctor(zend_accel_globals *accel_globals TSRMLS_DC) zend_accel_copy_internal_functions(TSRMLS_C); } +static void accel_globals_internal_func_dtor(zval *zv) +{ + free(Z_PTR_P(zv)); +} + static void accel_globals_dtor(zend_accel_globals *accel_globals TSRMLS_DC) { - accel_globals->function_table.pDestructor = NULL; + accel_globals->function_table.pDestructor = accel_globals_internal_func_dtor; zend_hash_destroy(&accel_globals->function_table); } @@ -2724,6 +2729,7 @@ void accel_shutdown(TSRMLS_D) #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO if (ZCG(accel_directives).interned_strings_buffer) { # ifndef ZTS + zend_hash_clean(CG(auto_globals)); zend_hash_clean(CG(function_table)); zend_hash_clean(CG(class_table)); zend_hash_clean(EG(zend_constants)); diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c index 3769e362fe..1ea652bc46 100644 --- a/ext/opcache/zend_accelerator_util_funcs.c +++ b/ext/opcache/zend_accelerator_util_funcs.c @@ -49,8 +49,9 @@ static int zend_prepare_function_for_execution(zend_op_array *op_array); static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind); static zend_ast *zend_ast_clone(zend_ast *ast TSRMLS_DC); -static void zend_accel_destroy_zend_function(zend_function *function) +static void zend_accel_destroy_zend_function(zval *zv) { + zend_function *function = Z_PTR_P(zv); TSRMLS_FETCH(); if (function->type == ZEND_USER_FUNCTION) { @@ -67,7 +68,7 @@ static void zend_accel_destroy_zend_function(zend_function *function) static void zend_accel_destroy_zend_class(zval *zv) { zend_class_entry *ce = Z_PTR_P(zv); - ce->function_table.pDestructor = (dtor_func_t) zend_accel_destroy_zend_function; + ce->function_table.pDestructor = zend_accel_destroy_zend_function; destroy_zend_class(zv); } @@ -150,8 +151,8 @@ int compact_persistent_script(zend_persistent_script *persistent_script) void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements) { if (destroy_elements) { - persistent_script->function_table.pDestructor = (dtor_func_t)zend_accel_destroy_zend_function; - persistent_script->class_table.pDestructor = (dtor_func_t)zend_accel_destroy_zend_class; + persistent_script->function_table.pDestructor = zend_accel_destroy_zend_function; + persistent_script->class_table.pDestructor = zend_accel_destroy_zend_class; } else { persistent_script->function_table.pDestructor = NULL; persistent_script->class_table.pDestructor = NULL; @@ -196,7 +197,8 @@ static int move_user_function(zval *zv #endif if (function->type == ZEND_USER_FUNCTION) { - zend_hash_update_mem(function_table, hash_key->key, function, sizeof(zend_function)); + zend_hash_update_ptr(function_table, hash_key->key, function); +//??? zend_hash_update_mem(function_table, hash_key->key, function, sizeof(zend_function)); return 1; } else { return 0; @@ -231,12 +233,15 @@ void zend_accel_copy_internal_functions(TSRMLS_D) ZCG(internal_functions_count) = zend_hash_num_elements(&ZCG(function_table)); } -static void zend_destroy_property_info(zend_property_info *property_info) +static void zend_destroy_property_info(zval *zv) { + zend_property_info *property_info = Z_PTR_P(zv); + STR_RELEASE(property_info->name); if (property_info->doc_comment) { STR_RELEASE(property_info->doc_comment); } + efree(property_info); } static inline void zend_clone_zval(zval *src, int bind TSRMLS_DC) @@ -250,15 +255,17 @@ static inline void zend_clone_zval(zval *src, int bind TSRMLS_DC) #endif case IS_STRING: case IS_CONSTANT: - if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_STR_P(src))) != NULL) { - Z_STR_P(src) = ptr; - } else { - zend_string *old = Z_STR_P(src); + if (!IS_INTERNED(Z_STR_P(src))) { + if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_STR_P(src))) != NULL) { + Z_STR_P(src) = ptr; + } else { + zend_string *old = Z_STR_P(src); - Z_STR_P(src) = STR_DUP(old, 0); - Z_STR_P(src)->gc = old->gc; - if (bind && Z_REFCOUNT_P(src) > 1) { - accel_xlat_set(old, Z_STR_P(src)); + Z_STR_P(src) = STR_DUP(old, 0); + Z_STR_P(src)->gc = old->gc; + if (bind && Z_REFCOUNT_P(src) > 1) { + accel_xlat_set(old, Z_STR_P(src)); + } } } break; @@ -513,7 +520,7 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla ht->nNumUsed = 0; ht->nNumOfElements = source->nNumOfElements; ht->nNextFreeElement = source->nNextFreeElement; - ht->pDestructor = (dtor_func_t) zend_destroy_property_info; + ht->pDestructor = zend_destroy_property_info; #if ZEND_DEBUG //??? ht->inconsistent = 0; #endif @@ -801,15 +808,17 @@ static int zend_hash_unique_copy_mem(HashTable *target, HashTable *source, uniqu { uint idx; Bucket *p; - void *t; + zval *t; for (idx = 0; idx < source->nNumUsed; idx++) { p = source->arData + idx; if (Z_TYPE(p->val) == IS_UNDEF) continue; if (p->key) { - if ((t = zend_hash_add_mem(target, p->key, Z_PTR(p->val), size)) != NULL) { + if ((t = zend_hash_add(target, p->key, &p->val)) != NULL) { + Z_PTR_P(t) = emalloc(size); + memcpy(Z_PTR_P(t), Z_PTR(p->val), size); if (pCopyConstructor) { - pCopyConstructor(t); + pCopyConstructor(Z_PTR_P(t)); } } else { if (p->key->len > 0 && p->key->val[0] == 0) { @@ -817,29 +826,33 @@ static int zend_hash_unique_copy_mem(HashTable *target, HashTable *source, uniqu #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO if (((zend_function*)Z_PTR(p->val))->common.fn_flags & ZEND_ACC_CLOSURE) { /* update closure */ - if ((t = zend_hash_update_mem(target, p->key, Z_PTR(p->val), size)) != NULL) { + if ((t = zend_hash_update(target, p->key, &p->val)) != NULL) { + Z_PTR_P(t) = emalloc(size); + memcpy(Z_PTR_P(t), Z_PTR(p->val), size); if (pCopyConstructor) { - pCopyConstructor(t); + pCopyConstructor(Z_PTR_P(t)); } } } else { /* ignore and wait for runtime */ } #endif - } else if (!ignore_dups && (t = zend_hash_find_ptr(target, p->key)) != NULL) { + } else if (!ignore_dups && (t = zend_hash_find(target, p->key)) != NULL) { *fail_data = Z_PTR(p->val); - *conflict_data = t; + *conflict_data = Z_PTR_P(t); return FAILURE; } } } else { - if (!zend_hash_index_exists(target, p->h) && (t = zend_hash_index_update_mem(target, p->h, Z_PTR(p->val), size)) != NULL) { + if (!zend_hash_index_exists(target, p->h) && (t = zend_hash_index_update(target, p->h, &p->val)) != NULL) { + Z_PTR_P(t) = emalloc(size); + memcpy(Z_PTR_P(t), Z_PTR(p->val), size); if (pCopyConstructor) { - pCopyConstructor(t); + pCopyConstructor(Z_PTR_P(t)); } - } else if (!ignore_dups && (t = zend_hash_index_find_ptr(target,p->h)) != NULL) { + } else if (!ignore_dups && (t = zend_hash_index_find(target,p->h)) != NULL) { *fail_data = Z_PTR(p->val); - *conflict_data = t; + *conflict_data = Z_PTR_P(t); return FAILURE; } } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index cfac1960a2..13287025bb 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -186,7 +186,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc if (op_array->filename) { /* do not free! PHP has centralized filename storage, compiler will free it */ - zend_accel_memdup_string(op_array->filename); + op_array->filename = zend_accel_memdup_string(op_array->filename); } if (main_persistent_script) { @@ -354,9 +354,13 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc for (i = 0; i < op_array->num_args; i++) { if (op_array->arg_info[i].name) { //??? zend_accel_store_interned_string(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1); + efree(op_array->arg_info[i].name); + op_array->arg_info[i].name = NULL; } if (op_array->arg_info[i].class_name) { //??? zend_accel_store_interned_string(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1); + efree(op_array->arg_info[i].class_name); + op_array->arg_info[i].class_name = NULL; } } } @@ -476,7 +480,7 @@ static void zend_persist_class_entry(zval *zv TSRMLS_DC) if (ZEND_CE_FILENAME(ce)) { /* do not free! PHP has centralized filename storage, compiler will free it */ - zend_accel_memdup_string(ZEND_CE_FILENAME(ce)); + ZEND_CE_FILENAME(ce) = zend_accel_memdup_string(ZEND_CE_FILENAME(ce)); } if (ZEND_CE_DOC_COMMENT(ce)) { if (ZCG(accel_directives).save_comments) { diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index 061a4e2777..73f331de6f 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -347,6 +347,7 @@ void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source TSRML ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size)); memcpy(retval, source, size); if (free_source) { + efree(source); //??? interned_efree((char*)source); } zend_shared_alloc_register_xlat_entry(source, retval);