@@ -29,6 +29,13 @@ php_ref_reference_t *php_ref_reference_init(zval *this_ptr, zval *referent_zv, z
2929static inline void php_ref_store_exceptions (zval * exceptions , zval * tmp );
3030static int php_ref_reference_check_notifier (zval * notifier , zval * this );
3131
32+ //#define PHP_REF_DEBUG 1
33+
34+ #ifdef PHP_REF_DEBUG
35+ #define php_ref_debug (format , ...) fprintf(stderr, format, ##__VA_ARGS__);
36+ #else
37+ #define php_ref_debug (format , ...)
38+ #endif
3239
3340php_ref_reference_t * php_ref_reference_fetch_object (zend_object * obj )
3441{
@@ -95,6 +102,8 @@ static void php_ref_nullify_referents(HashTable *references)
95102
96103 ZEND_HASH_REVERSE_FOREACH_PTR (references , reference ) {
97104 handle = _p -> h ;
105+
106+ reference -> referent -> tracked -- ;
98107 reference -> referent = NULL ;
99108
100109 zend_hash_index_del (references , handle );
@@ -142,6 +151,16 @@ static void php_ref_call_notifiers(HashTable *references, zval *exceptions, zval
142151
143152}
144153
154+ static void php_ref_maybe_restore_handlers (php_ref_referent_t * referent )
155+ {
156+ if (referent -> tracked ) {
157+ return ;
158+ }
159+
160+ Z_OBJ (referent -> this_ptr )-> handlers = referent -> original_handlers ;
161+ referent -> original_handlers = NULL ;
162+ }
163+
145164void php_ref_referent_object_dtor_obj (zend_object * object )
146165{
147166 php_ref_referent_t * referent = php_ref_referent_find_ptr (object -> handle );
@@ -174,8 +193,8 @@ void php_ref_referent_object_dtor_obj(zend_object *object)
174193 }
175194
176195 php_ref_nullify_referents (& referent -> soft_references );
177-
178196 php_ref_call_notifiers (& referent -> weak_references , & exceptions , & tmp , 1 );
197+ php_ref_maybe_restore_handlers (referent );
179198
180199 zend_hash_index_del (PHP_REF_G (referents ), referent -> handle );
181200 } else {
@@ -204,15 +223,23 @@ void php_ref_globals_referents_ht_dtor(zval *zv)
204223 zend_hash_destroy (& referent -> soft_references );
205224 zend_hash_destroy (& referent -> weak_references );
206225
207- Z_OBJ (referent -> this_ptr )-> handlers = referent -> original_handlers ;
226+ if (referent -> original_handlers ) {
227+ Z_OBJ (referent -> this_ptr )-> handlers = referent -> original_handlers ;
228+ referent -> original_handlers = NULL ;
229+ }
208230
209231 efree (referent );
210232}
211233
212- void php_ref_referent_weak_references_ht_dtor (zval * zv )
234+ void php_ref_referent_abstract_references_ht_dtor (zval * zv )
213235{
214236 php_ref_reference_t * reference = (php_ref_reference_t * ) Z_PTR_P (zv );
215237
238+ if (reference -> referent ) {
239+ reference -> referent -> tracked -- ;
240+ php_ref_maybe_restore_handlers (reference -> referent );
241+ }
242+
216243 /* clean links to ht & release callbacks as we don't need them already*/
217244 reference -> referent = NULL ; /* no need to free anything at this point here */
218245}
@@ -227,8 +254,10 @@ php_ref_referent_t *php_ref_referent_get_or_create(zval *referent_zv)
227254
228255 referent = (php_ref_referent_t * ) ecalloc (1 , sizeof (php_ref_referent_t ));
229256
230- zend_hash_init (& referent -> soft_references , 0 , NULL , NULL , 0 );
231- zend_hash_init (& referent -> weak_references , 0 , NULL , php_ref_referent_weak_references_ht_dtor , 0 );
257+ referent -> tracked = 0 ;
258+
259+ zend_hash_init (& referent -> soft_references , 0 , NULL , php_ref_referent_abstract_references_ht_dtor , 0 );
260+ zend_hash_init (& referent -> weak_references , 0 , NULL , php_ref_referent_abstract_references_ht_dtor , 0 );
232261
233262 referent -> original_handlers = Z_OBJ_P (referent_zv )-> handlers ;
234263
@@ -261,6 +290,7 @@ void php_ref_abstract_reference_maybe_unregister(php_ref_reference_t *reference)
261290void php_ref_soft_reference_attach (php_ref_reference_t * reference , php_ref_referent_t * referent )
262291{
263292 reference -> referent = referent ;
293+ referent -> tracked ++ ;
264294 zend_hash_index_add_ptr (& referent -> soft_references , (zend_ulong ) Z_OBJ_HANDLE_P (& reference -> this_ptr ), reference );
265295}
266296
@@ -281,6 +311,7 @@ void php_ref_soft_reference_maybe_unregister(php_ref_reference_t *reference)
281311void php_ref_reference_attach (php_ref_reference_t * reference , php_ref_referent_t * referent )
282312{
283313 reference -> referent = referent ;
314+ referent -> tracked ++ ;
284315 zend_hash_index_add_ptr (& referent -> weak_references , (zend_ulong ) Z_OBJ_HANDLE_P (& reference -> this_ptr ), reference );
285316}
286317
0 commit comments