Skip to content

Commit 69efd5c

Browse files
authored
PHPC-1737: Use zend_hash_graceful_reverse_destroy for persistent client HashTable (#1191)
Also improve comments for request-scoped HashTables
1 parent 5959c50 commit 69efd5c

File tree

1 file changed

+24
-22
lines changed

1 file changed

+24
-22
lines changed

php_phongo.c

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3722,23 +3722,29 @@ static void php_phongo_pclient_destroy_ptr(zval* ptr)
37223722
PHP_RINIT_FUNCTION(mongodb)
37233723
{
37243724
/* Initialize HashTable for non-persistent clients, which is initialized to
3725-
* NULL in GINIT and destroyed and reset to NULL in RSHUTDOWN. */
3725+
* NULL in GINIT and destroyed and reset to NULL in RSHUTDOWN. Although we
3726+
* specify an element destructor here, all request clients should be freed
3727+
* naturally via garbage collection (i.e. the HashTable should be empty at
3728+
* the time it is destroyed in RSHUTDOWN). */
37263729
if (MONGODB_G(request_clients) == NULL) {
37273730
ALLOC_HASHTABLE(MONGODB_G(request_clients));
37283731
zend_hash_init(MONGODB_G(request_clients), 0, NULL, php_phongo_pclient_destroy_ptr, 0);
37293732
}
37303733

37313734
/* Initialize HashTable for APM subscribers, which is initialized to NULL in
3732-
* GINIT and destroyed and reset to NULL in RSHUTDOWN. */
3735+
* GINIT and destroyed and reset to NULL in RSHUTDOWN. Since this HashTable
3736+
* will store subscriber object zvals, we specify ZVAL_PTR_DTOR as its
3737+
* element destructor so that any still-registered subscribers can be freed
3738+
* in RSHUTDOWN. */
37333739
if (MONGODB_G(subscribers) == NULL) {
37343740
ALLOC_HASHTABLE(MONGODB_G(subscribers));
37353741
zend_hash_init(MONGODB_G(subscribers), 0, NULL, ZVAL_PTR_DTOR, 0);
37363742
}
37373743

37383744
/* Initialize HashTable for registering Manager objects. This is initialized
37393745
* to NULL in GINIT and destroyed and reset to NULL in RSHUTDOWN. Since this
3740-
* HashTable stores pointers to existing php_phongo_manager_t objects, the
3741-
* element destructor is intentionally NULL. */
3746+
* HashTable stores pointers to existing php_phongo_manager_t objects (not
3747+
* counted references), the element destructor is intentionally NULL. */
37423748
if (MONGODB_G(managers) == NULL) {
37433749
ALLOC_HASHTABLE(MONGODB_G(managers));
37443750
zend_hash_init(MONGODB_G(managers), 0, NULL, NULL, 0);
@@ -3761,8 +3767,12 @@ PHP_GINIT_FUNCTION(mongodb)
37613767
/* Clear extension globals */
37623768
memset(mongodb_globals, 0, sizeof(zend_mongodb_globals));
37633769

3764-
/* Initialize HashTable for persistent clients */
3765-
zend_hash_init(&mongodb_globals->persistent_clients, 0, NULL, NULL, 1);
3770+
/* Initialize HashTable for persistent clients, which will be destroyed in
3771+
* GSHUTDOWN. We specify an element destructor so that persistent clients
3772+
* can be destroyed along with the HashTable. The HashTable's struct is
3773+
* nested within globals, so no allocation is needed (unlike the HashTables
3774+
* allocated in RINIT). */
3775+
zend_hash_init(&mongodb_globals->persistent_clients, 0, NULL, php_phongo_pclient_destroy_ptr, 1);
37663776
}
37673777
/* }}} */
37683778

@@ -3934,9 +3944,11 @@ PHP_RSHUTDOWN_FUNCTION(mongodb)
39343944

39353945
/* Destroy HashTable for non-persistent clients, which was initialized in
39363946
* RINIT. This is intentionally done after the APM subscribers to allow any
3937-
* non-persistent clients still referenced by a subscriber (not removed
3938-
* prior to RSHUTDOWN) to be naturally freed by the Manager's free_object
3939-
* handler rather than the HashTable's element destructor. */
3947+
* non-persistent clients still referenced by a subscriber (not freed prior
3948+
* to RSHUTDOWN) to be naturally garbage collected and freed by the Manager
3949+
* free_object handler rather than the HashTable's element destructor. There
3950+
* is no need to use zend_hash_graceful_reverse_destroy here like we do for
3951+
* persistent clients; moreover, the HashTable should already be empty. */
39403952
if (MONGODB_G(request_clients)) {
39413953
zend_hash_destroy(MONGODB_G(request_clients));
39423954
FREE_HASHTABLE(MONGODB_G(request_clients));
@@ -3957,20 +3969,10 @@ PHP_RSHUTDOWN_FUNCTION(mongodb)
39573969
/* {{{ PHP_GSHUTDOWN_FUNCTION */
39583970
PHP_GSHUTDOWN_FUNCTION(mongodb)
39593971
{
3960-
php_phongo_pclient_t* pclient;
3961-
3962-
/* Destroy mongoc_client_t objects in reverse order. This is necessary to
3963-
* prevent segmentation faults as clients may reference other clients in
3972+
/* Destroy persistent client HashTable in reverse order. This is necessary
3973+
* to prevent segmentation faults as clients may reference other clients in
39643974
* encryption settings. */
3965-
ZEND_HASH_REVERSE_FOREACH_PTR(&mongodb_globals->persistent_clients, pclient)
3966-
{
3967-
php_phongo_pclient_destroy(pclient);
3968-
}
3969-
ZEND_HASH_FOREACH_END();
3970-
3971-
/* Destroy HashTable for persistent clients. mongoc_client_t objects have
3972-
* already been destroyed. */
3973-
zend_hash_destroy(&mongodb_globals->persistent_clients);
3975+
zend_hash_graceful_reverse_destroy(&mongodb_globals->persistent_clients);
39743976

39753977
mongodb_globals->debug = NULL;
39763978
if (mongodb_globals->debug_fd) {

0 commit comments

Comments
 (0)