Skip to content
This repository was archived by the owner on Jul 7, 2018. It is now read-only.

Commit 722ce87

Browse files
authored
Merge pull request #24 from pinepain/fix-beta-72
Restore original referent obj handler when it is no longer tracked
2 parents 398b6d1 + 358f734 commit 722ce87

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

php_ref_reference.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ php_ref_reference_t *php_ref_reference_init(zval *this_ptr, zval *referent_zv, z
2929
static inline void php_ref_store_exceptions(zval *exceptions, zval *tmp);
3030
static 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

3340
php_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+
145164
void 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)
261290
void 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)
281311
void 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

php_ref_reference.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ struct _php_ref_referent_t {
5252

5353
HashTable soft_references;
5454
HashTable weak_references;
55+
56+
uint32_t tracked;
5557
};
5658

5759
struct _php_ref_reference_t {

0 commit comments

Comments
 (0)