]> granicus.if.org Git - php/commitdiff
- MFH Fix issue with destruction of overloaded objects
authorMarcus Boerger <helly@php.net>
Sun, 24 Aug 2008 16:49:19 +0000 (16:49 +0000)
committerMarcus Boerger <helly@php.net>
Sun, 24 Aug 2008 16:49:19 +0000 (16:49 +0000)
Zend/zend_gc.c
Zend/zend_objects.c
Zend/zend_objects_API.c
Zend/zend_objects_API.h

index bd455c481ca6e5e0b44d77af385b41b1f9c5ea8d..8571cd7b667e941604b6a6b5402c49d0cf649fd9 100644 (file)
@@ -575,7 +575,7 @@ ZEND_API int gc_collect_cycles(TSRMLS_D)
                                        EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount <= 0) {
                                        EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount = 1;
                                        Z_TYPE(p->z) = IS_NULL;
-                                       zend_objects_store_del_ref_by_handle(Z_OBJ_HANDLE(p->z) TSRMLS_CC);
+                                       zend_objects_store_del_ref_by_handle_ex(Z_OBJ_HANDLE(p->z), Z_OBJ_HT(p->z) TSRMLS_CC);
                                }
                        } else if (Z_TYPE(p->z) == IS_ARRAY) {
                                Z_TYPE(p->z) = IS_NULL;
index 12aebc7c5609cbfae95bc9d929ea298f9e6d8b8d..9f09af994640f3447c80656a78cd740483f48e31 100644 (file)
@@ -53,6 +53,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
 
        if (destructor) {
                zval *obj;
+               zend_object_store_bucket *obj_bucket;
 
                if (destructor->op_array.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) {
                        if (destructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
@@ -87,8 +88,11 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
                MAKE_STD_ZVAL(obj);
                Z_TYPE_P(obj) = IS_OBJECT;
                Z_OBJ_HANDLE_P(obj) = handle;
-               /* TODO: We cannot set proper handlers. */
-               Z_OBJ_HT_P(obj) = &std_object_handlers; 
+               obj_bucket = &EG(objects_store).object_buckets[handle];
+               if (!obj_bucket->bucket.obj.handlers) {
+                       obj_bucket->bucket.obj.handlers = &std_object_handlers;
+               }
+               Z_OBJ_HT_P(obj) = obj_bucket->bucket.obj.handlers;
                zval_copy_ctor(obj);
 
                /* Make sure that destructors are protected from previously thrown exceptions.
index 154980fd11e89562560a5f376ebc55126d0551a0..dfda720b0ff5ae2a278c8b03bd4f76102df878b0 100644 (file)
@@ -122,8 +122,8 @@ ZEND_API zend_object_handle zend_objects_store_put(void *object, zend_objects_st
        obj->object = object;
        obj->dtor = dtor?dtor:(zend_objects_store_dtor_t)zend_objects_destroy_object;
        obj->free_storage = free_storage;
-
        obj->clone = clone;
+       obj->handlers = NULL;
 
 #if ZEND_DEBUG_OBJECTS
        fprintf(stderr, "Allocated object id #%d\n", handle);
@@ -168,7 +168,7 @@ ZEND_API void zend_objects_store_del_ref(zval *zobject TSRMLS_DC)
        handle = Z_OBJ_HANDLE_P(zobject);
 
        Z_ADDREF_P(zobject);
-       zend_objects_store_del_ref_by_handle(handle TSRMLS_CC);
+       zend_objects_store_del_ref_by_handle_ex(handle, Z_OBJ_HT_P(zobject) TSRMLS_CC);
        Z_DELREF_P(zobject);
 
        GC_ZOBJ_CHECK_POSSIBLE_ROOT(zobject);
@@ -177,7 +177,7 @@ ZEND_API void zend_objects_store_del_ref(zval *zobject TSRMLS_DC)
 /*
  * Delete a reference to an objects store entry given the object handle.
  */
-ZEND_API void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSRMLS_DC)
+ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, const zend_object_handlers *handlers TSRMLS_DC) /* {{{ */
 {
        struct _store_object *obj;
        int failure = 0;
@@ -198,6 +198,9 @@ ZEND_API void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSR
                                EG(objects_store).object_buckets[handle].destructor_called = 1;
 
                                if (obj->dtor) {
+                                       if (handlers && !obj->handlers) {
+                                               obj->handlers = handlers;
+                                       }
                                        zend_try {
                                                obj->dtor(obj->object, handle TSRMLS_CC);
                                        } zend_catch {
@@ -232,6 +235,7 @@ ZEND_API void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSR
                zend_bailout();
        }
 }
+/* }}} */
 
 ZEND_API zend_object_value zend_objects_store_clone_obj(zval *zobject TSRMLS_DC)
 {
@@ -250,6 +254,7 @@ ZEND_API zend_object_value zend_objects_store_clone_obj(zval *zobject TSRMLS_DC)
 
        retval.handle = zend_objects_store_put(new_object, obj->dtor, obj->free_storage, obj->clone TSRMLS_CC);
        retval.handlers = Z_OBJ_HT_P(zobject);
+       EG(objects_store).object_buckets[handle].bucket.obj.handlers = retval.handlers;
 
        return retval;
 }
@@ -288,8 +293,10 @@ ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC
 ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC)
 {
        zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
-
-       EG(objects_store).object_buckets[handle].destructor_called = 1;
+       zend_object_store_bucket *obj_bucket = &EG(objects_store).object_buckets[handle];
+       
+       obj_bucket->bucket.obj.handlers = Z_OBJ_HT_P(zobject);;
+       obj_bucket->destructor_called = 1;
 }
 
 
index f89ff242517768d887592b1ca861af1c5ebf8161..ed510f5eb9201e0e9f0f2ac2d0f62f5a207615e2 100644 (file)
@@ -37,6 +37,7 @@ typedef struct _zend_object_store_bucket {
                        zend_objects_store_dtor_t dtor;
                        zend_objects_free_object_storage_t free_storage;
                        zend_objects_store_clone_t clone;
+                       const zend_object_handlers *handlers;
                        zend_uint refcount;
                        gc_root_buffer *buffered;
                } obj;
@@ -66,7 +67,10 @@ ZEND_API zend_object_handle zend_objects_store_put(void *object, zend_objects_st
 ZEND_API void zend_objects_store_add_ref(zval *object TSRMLS_DC);
 ZEND_API void zend_objects_store_del_ref(zval *object TSRMLS_DC);
 ZEND_API void zend_objects_store_add_ref_by_handle(zend_object_handle handle TSRMLS_DC);
-ZEND_API void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSRMLS_DC);
+ZEND_API void zend_objects_store_del_ref_by_handle_ex(zend_object_handle handle, const zend_object_handlers *handlers TSRMLS_DC);
+static inline void zend_objects_store_del_ref_by_handle(zend_object_handle handle TSRMLS_DC) {
+       zend_objects_store_del_ref_by_handle_ex(handle, NULL TSRMLS_CC);
+}
 ZEND_API zend_uint zend_objects_store_get_refcount(zval *object TSRMLS_DC);
 ZEND_API zend_object_value zend_objects_store_clone_obj(zval *object TSRMLS_DC);
 ZEND_API void *zend_object_store_get_object(const zval *object TSRMLS_DC);