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