Hi, Attached is a fix for bug #25543 (Error in set_error_handler() definition), which is caused by disordered scheduling of the garbage collection (zend_clean_garbage()).
With this patch I'm adding the following two inline functions, zend_begin_atomic() and zend_end_atomic(), to prevent GC from being performed at the right time. Calls to those functions are inserted at the beginning / end of zend_fetch_dimension_address(), zend_fetch_property_address(), and some other functions of the same kind. I'll commit these shortly if you don't see any problem. Regards, Moriyoshi
Index: Zend/zend.c =================================================================== RCS file: /repository/Zend/Attic/zend.c,v retrieving revision 1.162.2.13 diff -u -r1.162.2.13 zend.c --- Zend/zend.c 22 Sep 2003 04:22:06 -0000 1.162.2.13 +++ Zend/zend.c 3 Oct 2003 00:13:47 -0000 @@ -501,6 +501,7 @@ zend_startup_constants(); zend_set_default_compile_time_values(TSRMLS_C); EG(user_error_handler) = NULL; + EG(atomic_op_count) = 0; #endif zend_register_standard_constants(TSRMLS_C); Index: Zend/zend_execute.c =================================================================== RCS file: /repository/Zend/Attic/zend_execute.c,v retrieving revision 1.316.2.22 diff -u -r1.316.2.22 zend_execute.c --- Zend/zend_execute.c 28 Aug 2003 16:08:11 -0000 1.316.2.22 +++ Zend/zend_execute.c 3 Oct 2003 00:13:48 -0000 @@ -739,9 +739,11 @@ zval *container; zval ***retval = &Ts[result->u.var].var.ptr_ptr; + zend_begin_atomic(TSRMLS_C); if (container_ptr == NULL) { fetch_overloaded_element(result, op1, op2, Ts, type, retval, OE_IS_ARRAY TSRMLS_CC); + zend_end_atomic(TSRMLS_C); return; } @@ -750,6 +752,7 @@ if (container == EG(error_zval_ptr)) { *retval = &EG(error_zval_ptr); SELECTIVE_PZVAL_LOCK(**retval, result); + zend_end_atomic(TSRMLS_C); return; } @@ -824,7 +827,6 @@ Ts[result->u.var].EA.type = IS_STRING_OFFSET; FREE_OP(Ts, op2, EG(free_op2)); *retval = NULL; - return; } break; default: { @@ -844,6 +846,7 @@ } break; } + zend_end_atomic(TSRMLS_C); } @@ -869,9 +872,11 @@ zval *container; zval ***retval = &Ts[result->u.var].var.ptr_ptr; + zend_begin_atomic(TSRMLS_C); if (container_ptr == NULL) { fetch_overloaded_element(result, op1, op2, Ts, type, retval, OE_IS_OBJECT TSRMLS_CC); + zend_end_atomic(TSRMLS_C); return; } @@ -879,6 +884,7 @@ if (container == EG(error_zval_ptr)) { *retval = &EG(error_zval_ptr); SELECTIVE_PZVAL_LOCK(**retval, result); + zend_end_atomic(TSRMLS_C); return; } @@ -899,6 +905,7 @@ zend_llist_add_element(Ts[result->u.var].EA.data.overloaded_element.elements_list, &overloaded_element); Ts[result->u.var].EA.type = IS_OVERLOADED_OBJECT; *retval = NULL; + zend_end_atomic(TSRMLS_C); return; } @@ -929,6 +936,7 @@ *retval = &EG(error_zval_ptr); } SELECTIVE_PZVAL_LOCK(**retval, result); + zend_end_atomic(TSRMLS_C); return; } @@ -939,6 +947,7 @@ } *retval = zend_fetch_property_address_inner(Z_OBJPROP_P(container), op2, Ts, type TSRMLS_CC); SELECTIVE_PZVAL_LOCK(**retval, result); + zend_end_atomic(TSRMLS_C); } Index: Zend/zend_execute.h =================================================================== RCS file: /repository/Zend/Attic/zend_execute.h,v retrieving revision 1.47.2.1 diff -u -r1.47.2.1 zend_execute.h --- Zend/zend_execute.h 31 Dec 2002 16:23:00 -0000 1.47.2.1 +++ Zend/zend_execute.h 3 Oct 2003 00:13:48 -0000 @@ -112,6 +112,15 @@ void execute_new_code(TSRMLS_D); +static inline void zend_begin_atomic(TSRMLS_D) +{ + EG(atomic_op_count)++; +} + +static inline void zend_end_atomic(TSRMLS_D) +{ + EG(atomic_op_count)--; +} /* services */ ZEND_API char *get_active_function_name(TSRMLS_D); Index: Zend/zend_execute_locks.h =================================================================== RCS file: /repository/Zend/Attic/zend_execute_locks.h,v retrieving revision 1.9 diff -u -r1.9 zend_execute_locks.h --- Zend/zend_execute_locks.h 31 Aug 2001 19:32:25 -0000 1.9 +++ Zend/zend_execute_locks.h 3 Oct 2003 00:13:48 -0000 @@ -22,8 +22,10 @@ static inline void zend_clean_garbage(TSRMLS_D) { - while (EG(garbage_ptr)) { - zval_ptr_dtor(&EG(garbage)[--EG(garbage_ptr)]); + if (!EG(atomic_op_count)) { + while (EG(garbage_ptr)) { + zval_ptr_dtor(&EG(garbage)[--EG(garbage_ptr)]); + } } } Index: Zend/zend_globals.h =================================================================== RCS file: /repository/Zend/Attic/zend_globals.h,v retrieving revision 1.93.2.4 diff -u -r1.93.2.4 zend_globals.h --- Zend/zend_globals.h 31 May 2003 01:37:43 -0000 1.93.2.4 +++ Zend/zend_globals.h 3 Oct 2003 00:13:48 -0000 @@ -210,6 +210,8 @@ /* locale stuff */ char float_separator[1]; + int atomic_op_count; + void *reserved[ZEND_MAX_RESERVED_RESOURCES]; };
Index: Zend/zend.c =================================================================== RCS file: /repository/ZendEngine2/zend.c,v retrieving revision 1.252 diff -u -r1.252 zend.c --- Zend/zend.c 22 Sep 2003 04:21:44 -0000 1.252 +++ Zend/zend.c 3 Oct 2003 00:17:36 -0000 @@ -618,6 +618,7 @@ zend_set_default_compile_time_values(TSRMLS_C); EG(user_error_handler) = NULL; EG(user_exception_handler) = NULL; + EG(atomic_op_count) = 0; #endif register_standard_class(TSRMLS_C); zend_register_standard_constants(TSRMLS_C); Index: Zend/zend_execute.c =================================================================== RCS file: /repository/ZendEngine2/zend_execute.c,v retrieving revision 1.540 diff -u -r1.540 zend_execute.c --- Zend/zend_execute.c 17 Sep 2003 11:06:11 -0000 1.540 +++ Zend/zend_execute.c 3 Oct 2003 00:17:37 -0000 @@ -71,8 +71,10 @@ static inline void zend_clean_garbage(TSRMLS_D) { - while (EG(garbage_ptr)) { - zval_ptr_dtor(&EG(garbage)[--EG(garbage_ptr)]); + if (!EG(atomic_op_count)) { + while (EG(garbage_ptr)) { + zval_ptr_dtor(&EG(garbage)[--EG(garbage_ptr)]); + } } } @@ -827,6 +829,8 @@ zval *container; zval ***retval = &T(result->u.var).var.ptr_ptr; + zend_begin_atomic(TSRMLS_C); + if (!container_ptr) { if (T(op1->u.var).EA.type == IS_STRING_OFFSET) { zend_error(E_WARNING, "Cannot use string offset as an array"); @@ -836,6 +840,7 @@ } *retval = &EG(error_zval_ptr); SELECTIVE_PZVAL_LOCK(**retval, result); + zend_end_atomic(TSRMLS_C); return; } @@ -844,6 +849,7 @@ if (container == EG(error_zval_ptr)) { *retval = &EG(error_zval_ptr); SELECTIVE_PZVAL_LOCK(**retval, result); + zend_end_atomic(TSRMLS_C); return; } @@ -918,7 +924,6 @@ T(result->u.var).EA.type = IS_STRING_OFFSET; FREE_OP(Ts, op2, EG(free_op2)); *retval = NULL; - return; } break; case IS_OBJECT: @@ -951,6 +956,7 @@ } break; } + zend_end_atomic(TSRMLS_C); } @@ -974,11 +980,14 @@ zval **container_ptr = get_obj_zval_ptr_ptr(op1, Ts, type TSRMLS_CC); zval *container; zval ***retval = &T(result->u.var).var.ptr_ptr; + + zend_begin_atomic(TSRMLS_C); container = *container_ptr; if (container == EG(error_zval_ptr)) { *retval = &EG(error_zval_ptr); SELECTIVE_PZVAL_LOCK(**retval, result); + zend_end_atomic(TSRMLS_C); return; } /* this should modify object only if it's empty */ @@ -1006,6 +1015,7 @@ *retval = &EG(error_zval_ptr); } SELECTIVE_PZVAL_LOCK(**retval, result); + zend_end_atomic(TSRMLS_C); return; } @@ -1016,6 +1026,7 @@ } *retval = zend_fetch_property_address_inner(container, op2, Ts, type TSRMLS_CC); SELECTIVE_PZVAL_LOCK(**retval, result); + zend_end_atomic(TSRMLS_C); } static void zend_fetch_property_address_read(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type TSRMLS_DC) @@ -1026,14 +1037,16 @@ retval = &T(result->u.var).var.ptr; T(result->u.var).var.ptr_ptr = retval; + zend_begin_atomic(TSRMLS_C); + container = get_obj_zval_ptr(op1, Ts, &EG(free_op1), type TSRMLS_CC); if (container == EG(error_zval_ptr)) { *retval = EG(error_zval_ptr); SELECTIVE_PZVAL_LOCK(*retval, result); + zend_end_atomic(TSRMLS_C); return; } - if (container->type != IS_OBJECT) { zend_error(E_NOTICE, "Trying to get property of non-object"); @@ -1072,7 +1085,7 @@ } SELECTIVE_PZVAL_LOCK(*retval, result); - return; + zend_end_atomic(TSRMLS_C); } static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC) @@ -1083,6 +1096,8 @@ zval **retval = &T(result->u.var).var.ptr; int have_get_ptr = 0; + zend_begin_atomic(TSRMLS_C); + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -1092,6 +1107,7 @@ *retval = EG(uninitialized_zval_ptr); SELECTIVE_PZVAL_LOCK(*retval, result); + zend_end_atomic(TSRMLS_C); return; } @@ -1120,6 +1136,7 @@ } FREE_OP(Ts, op2, EG(free_op2)); + zend_end_atomic(TSRMLS_C); } static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC) @@ -1130,6 +1147,8 @@ zval *retval = &T(result->u.var).tmp_var; int have_get_ptr = 0; + zend_begin_atomic(TSRMLS_C); + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; @@ -1137,6 +1156,7 @@ zend_error(E_WARNING, "Attempt to increment/decrement property of non-object"); FREE_OP(Ts, op2, EG(free_op2)); *retval = *EG(uninitialized_zval_ptr); + zend_end_atomic(TSRMLS_C); return; } @@ -1169,6 +1189,7 @@ } FREE_OP(Ts, op2, EG(free_op2)); + zend_end_atomic(TSRMLS_C); } Index: Zend/zend_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_execute.h,v retrieving revision 1.58 diff -u -r1.58 zend_execute.h --- Zend/zend_execute.h 24 Aug 2003 13:10:02 -0000 1.58 +++ Zend/zend_execute.h 3 Oct 2003 00:17:37 -0000 @@ -138,6 +138,15 @@ void execute_new_code(TSRMLS_D); +static inline void zend_begin_atomic(TSRMLS_D) +{ + EG(atomic_op_count)++; +} + +static inline void zend_end_atomic(TSRMLS_D) +{ + EG(atomic_op_count)--; +} /* services */ ZEND_API char *get_active_function_name(TSRMLS_D); Index: Zend/zend_globals.h =================================================================== RCS file: /repository/ZendEngine2/zend_globals.h,v retrieving revision 1.128 diff -u -r1.128 zend_globals.h --- Zend/zend_globals.h 11 Aug 2003 05:24:41 -0000 1.128 +++ Zend/zend_globals.h 3 Oct 2003 00:17:38 -0000 @@ -234,6 +234,8 @@ /* locale stuff */ char float_separator[1]; + int atomic_op_count; + void *reserved[ZEND_MAX_RESERVED_RESOURCES]; };
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php