@@ -29,6 +29,13 @@ php_ref_reference_t *php_ref_reference_init(zval *this_ptr, zval *referent_zv, z
29
29
static inline void php_ref_store_exceptions (zval * exceptions , zval * tmp );
30
30
static int php_ref_reference_check_notifier (zval * notifier , zval * this );
31
31
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
32
39
33
40
php_ref_reference_t * php_ref_reference_fetch_object (zend_object * obj )
34
41
{
@@ -95,6 +102,8 @@ static void php_ref_nullify_referents(HashTable *references)
95
102
96
103
ZEND_HASH_REVERSE_FOREACH_PTR (references , reference ) {
97
104
handle = _p -> h ;
105
+
106
+ reference -> referent -> tracked -- ;
98
107
reference -> referent = NULL ;
99
108
100
109
zend_hash_index_del (references , handle );
@@ -142,6 +151,16 @@ static void php_ref_call_notifiers(HashTable *references, zval *exceptions, zval
142
151
143
152
}
144
153
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
+
145
164
void php_ref_referent_object_dtor_obj (zend_object * object )
146
165
{
147
166
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)
174
193
}
175
194
176
195
php_ref_nullify_referents (& referent -> soft_references );
177
-
178
196
php_ref_call_notifiers (& referent -> weak_references , & exceptions , & tmp , 1 );
197
+ php_ref_maybe_restore_handlers (referent );
179
198
180
199
zend_hash_index_del (PHP_REF_G (referents ), referent -> handle );
181
200
} else {
@@ -204,15 +223,23 @@ void php_ref_globals_referents_ht_dtor(zval *zv)
204
223
zend_hash_destroy (& referent -> soft_references );
205
224
zend_hash_destroy (& referent -> weak_references );
206
225
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
+ }
208
230
209
231
efree (referent );
210
232
}
211
233
212
- void php_ref_referent_weak_references_ht_dtor (zval * zv )
234
+ void php_ref_referent_abstract_references_ht_dtor (zval * zv )
213
235
{
214
236
php_ref_reference_t * reference = (php_ref_reference_t * ) Z_PTR_P (zv );
215
237
238
+ if (reference -> referent ) {
239
+ reference -> referent -> tracked -- ;
240
+ php_ref_maybe_restore_handlers (reference -> referent );
241
+ }
242
+
216
243
/* clean links to ht & release callbacks as we don't need them already*/
217
244
reference -> referent = NULL ; /* no need to free anything at this point here */
218
245
}
@@ -227,8 +254,10 @@ php_ref_referent_t *php_ref_referent_get_or_create(zval *referent_zv)
227
254
228
255
referent = (php_ref_referent_t * ) ecalloc (1 , sizeof (php_ref_referent_t ));
229
256
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 );
232
261
233
262
referent -> original_handlers = Z_OBJ_P (referent_zv )-> handlers ;
234
263
@@ -261,6 +290,7 @@ void php_ref_abstract_reference_maybe_unregister(php_ref_reference_t *reference)
261
290
void php_ref_soft_reference_attach (php_ref_reference_t * reference , php_ref_referent_t * referent )
262
291
{
263
292
reference -> referent = referent ;
293
+ referent -> tracked ++ ;
264
294
zend_hash_index_add_ptr (& referent -> soft_references , (zend_ulong ) Z_OBJ_HANDLE_P (& reference -> this_ptr ), reference );
265
295
}
266
296
@@ -281,6 +311,7 @@ void php_ref_soft_reference_maybe_unregister(php_ref_reference_t *reference)
281
311
void php_ref_reference_attach (php_ref_reference_t * reference , php_ref_referent_t * referent )
282
312
{
283
313
reference -> referent = referent ;
314
+ referent -> tracked ++ ;
284
315
zend_hash_index_add_ptr (& referent -> weak_references , (zend_ulong ) Z_OBJ_HANDLE_P (& reference -> this_ptr ), reference );
285
316
}
286
317
0 commit comments