diff --git a/package.xml b/package.xml index 707a84a..dd1d6ea 100644 --- a/package.xml +++ b/package.xml @@ -15,9 +15,9 @@ http://pear.php.net/dtd/package-2.0.xsd"> colder@php.net yes - 2016-12-13 + 2018-08-09 - 0.3.3 + 0.4.0 0.3.1 @@ -25,9 +25,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> beta PHP - -- Restore dtors to prevent crash in multi-requests scenario - + Fixes to run on PHP 7.3 @@ -77,6 +75,12 @@ http://pear.php.net/dtd/package-2.0.xsd"> weakref + + betabeta + 0.4.00.3.1 + 2018-08-09 + Fixes to run on PHP 7.3 + betabeta 0.3.30.3.1 diff --git a/php_weakref.h b/php_weakref.h index f2eb26b..ab5c795 100644 --- a/php_weakref.h +++ b/php_weakref.h @@ -23,7 +23,7 @@ #include -#define PHP_WEAKREF_VERSION "0.3.3" +#define PHP_WEAKREF_VERSION "0.4.0" #ifdef PHP_WIN32 #define WEAKREF_API __declspec(dllexport) diff --git a/wr_store.c b/wr_store.c index 3557e2b..cbb2894 100644 --- a/wr_store.c +++ b/wr_store.c @@ -32,23 +32,29 @@ void wr_store_init() /* {{{ */ { wr_store *store = emalloc(sizeof(wr_store)); - zend_hash_init(&store->old_dtors, 0, NULL, NULL, 0); + zend_hash_init(&store->old_handlers, 0, NULL, NULL, 0); zend_hash_init(&store->objs, 0, NULL, NULL, 0); WR_G(store) = store; } /* }}} */ + +void wr_store_restore_handlers(zend_object *object, zend_object_handlers* handlers) { + efree((zend_object_handlers*)object->handlers); + object->handlers = handlers; +} + void wr_store_destroy() /* {{{ */ { wr_store *store = WR_G(store); - zend_object_dtor_obj_t orig_dtor; + zend_object_handlers* orig_handlers; ulong key; - ZEND_HASH_FOREACH_NUM_KEY_PTR(&store->old_dtors, key, orig_dtor) { - ((zend_object_handlers *)key)->dtor_obj = orig_dtor; + ZEND_HASH_FOREACH_NUM_KEY_PTR(&store->old_handlers, key, orig_handlers) { + wr_store_restore_handlers((zend_object *)key, orig_handlers); } ZEND_HASH_FOREACH_END(); - zend_hash_destroy(&store->old_dtors); + zend_hash_destroy(&store->old_handlers); zend_hash_destroy(&store->objs); efree(store); @@ -61,12 +67,16 @@ void wr_store_destroy() /* {{{ */ void wr_store_tracked_object_dtor(zend_object *ref_obj) /* {{{ */ { wr_store *store = WR_G(store); - zend_object_dtor_obj_t orig_dtor = zend_hash_index_find_ptr(&store->old_dtors, (ulong)ref_obj->handlers); + ulong handlers_key = (ulong)ref_obj; + zend_object_handlers *orig_handlers = zend_hash_index_find_ptr(&store->old_handlers, handlers_key); ulong handle_key = ref_obj->handle; wr_ref_list *list_entry; /* Original dtor has been called, we invalidate the necessary weakrefs: */ - orig_dtor(ref_obj); + orig_handlers->dtor_obj(ref_obj); + + wr_store_restore_handlers((zend_object *)handlers_key, orig_handlers); + zend_hash_index_del(&store->old_handlers, handlers_key); if ((list_entry = zend_hash_index_find_ptr(&store->objs, handle_key)) != NULL) { /* Invalidate wrefs_head while dtoring, to prevent detach on same wr */ @@ -89,12 +99,16 @@ void wr_store_tracked_object_dtor(zend_object *ref_obj) /* {{{ */ void wr_store_track(zend_object *wref_obj, wr_ref_dtor dtor, zend_object *ref_obj) /* {{{ */ { wr_store *store = WR_G(store); - ulong handlers_key = (ulong)ref_obj->handlers; + ulong handlers_key = (ulong)ref_obj; ulong handle_key = ref_obj->handle; - if (zend_hash_index_find_ptr(&store->old_dtors, handlers_key) == NULL) { - zend_hash_index_update_ptr(&store->old_dtors, handlers_key, ref_obj->handlers->dtor_obj); - ((zend_object_handlers *)ref_obj->handlers)->dtor_obj = wr_store_tracked_object_dtor; + if (zend_hash_index_find_ptr(&store->old_handlers, handlers_key) == NULL) { + size_t size = sizeof(zend_object_handlers); + zend_hash_index_update_ptr(&store->old_handlers, handlers_key, ref_obj->handlers); + zend_object_handlers* handlers = emalloc(size); + memcpy(handlers, ref_obj->handlers, size); + handlers->dtor_obj = wr_store_tracked_object_dtor; + ref_obj->handlers = handlers; } wr_ref_list *tail = zend_hash_index_find_ptr(&store->objs, handle_key); diff --git a/wr_store.h b/wr_store.h index 8da1843..f0f77ba 100644 --- a/wr_store.h +++ b/wr_store.h @@ -37,14 +37,9 @@ typedef struct _wr_ref_list { struct _wr_ref_list *next; } wr_ref_list; -typedef struct _wr_store_data { - zend_object_dtor_obj_t orig_dtor; - wr_ref_list *wrefs_head; -} wr_store_data; - typedef struct _wr_store { HashTable objs; - HashTable old_dtors; + HashTable old_handlers; } wr_store; void wr_store_init(TSRMLS_D); @@ -52,6 +47,7 @@ void wr_store_destroy(TSRMLS_D); void wr_store_tracked_object_dtor(zend_object *ref_obj); void wr_store_track(zend_object *wref_obj, wr_ref_dtor dtor, zend_object *ref_obj); void wr_store_untrack(zend_object *wref_obj, zend_object *ref_obj); +void wr_store_restore_handlers(zend_object *object, zend_object_handlers* orig_handlers); #endif /* PHP_WEAKREF_H */ diff --git a/wr_weakref.c b/wr_weakref.c index b7eb7e6..fadd5f3 100644 --- a/wr_weakref.c +++ b/wr_weakref.c @@ -38,13 +38,16 @@ static inline wr_weakref_object* wr_weakref_fetch(zend_object *obj) { #define Z_WEAKREF_OBJ_P(zv) wr_weakref_fetch(Z_OBJ_P(zv)); +#if PHP_VERSION_ID < 70300 +#define GC_ADDREF(p) ++GC_REFCOUNT(p) +#endif static int wr_weakref_ref_acquire(wr_weakref_object *wref) /* {{{ */ { if (wref->valid) { if (wref->acquired == 0) { // From now on we hold a proper reference - GC_REFCOUNT(wref->ref_obj)++; + GC_ADDREF(wref->ref_obj); } wref->acquired++; return SUCCESS; @@ -123,36 +126,6 @@ static zend_object* wr_weakref_object_new_ex(zend_class_entry *ce, zend_object * // NOOP } } - //if (clone_orig && orig) { - //wr_weakref_object *other = (wr_weakref_object *)zend_object_store_get_object(orig); - //if (other->valid) { - // int acquired = 0; - - // intern->valid = other->valid; - // ALLOC_INIT_ZVAL(intern->ref); - // // ZVAL_COPY_VALUE - // intern->ref->value = other->ref->value; - // Z_TYPE_P(intern->ref) = Z_TYPE_P(other->ref); - - // wr_store_track((zend_object *)intern, wr_weakref_ref_dtor, other->ref); - - // for (acquired = 0; acquired < other->acquired; acquired++) { - // wr_weakref_ref_acquire(intern); - // } - - // if (intern->acquired != other->acquired) { - // // shouldn't occur - // zend_throw_exception(spl_ce_RuntimeException, "Failed to correctly acquire clone's reference", 0); - // } - - //} else { - // intern->valid = 0; - // intern->ref_obj = NULL; - // intern->acquired = 0; - //} - //} else { - - //} wref->std.handlers = &wr_handler_WeakRef;