@@ -3722,23 +3722,29 @@ static void php_phongo_pclient_destroy_ptr(zval* ptr)
3722
3722
PHP_RINIT_FUNCTION (mongodb )
3723
3723
{
3724
3724
/* 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). */
3726
3729
if (MONGODB_G (request_clients ) == NULL ) {
3727
3730
ALLOC_HASHTABLE (MONGODB_G (request_clients ));
3728
3731
zend_hash_init (MONGODB_G (request_clients ), 0 , NULL , php_phongo_pclient_destroy_ptr , 0 );
3729
3732
}
3730
3733
3731
3734
/* 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. */
3733
3739
if (MONGODB_G (subscribers ) == NULL ) {
3734
3740
ALLOC_HASHTABLE (MONGODB_G (subscribers ));
3735
3741
zend_hash_init (MONGODB_G (subscribers ), 0 , NULL , ZVAL_PTR_DTOR , 0 );
3736
3742
}
3737
3743
3738
3744
/* Initialize HashTable for registering Manager objects. This is initialized
3739
3745
* 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. */
3742
3748
if (MONGODB_G (managers ) == NULL ) {
3743
3749
ALLOC_HASHTABLE (MONGODB_G (managers ));
3744
3750
zend_hash_init (MONGODB_G (managers ), 0 , NULL , NULL , 0 );
@@ -3761,8 +3767,12 @@ PHP_GINIT_FUNCTION(mongodb)
3761
3767
/* Clear extension globals */
3762
3768
memset (mongodb_globals , 0 , sizeof (zend_mongodb_globals ));
3763
3769
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 );
3766
3776
}
3767
3777
/* }}} */
3768
3778
@@ -3934,9 +3944,11 @@ PHP_RSHUTDOWN_FUNCTION(mongodb)
3934
3944
3935
3945
/* Destroy HashTable for non-persistent clients, which was initialized in
3936
3946
* 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. */
3940
3952
if (MONGODB_G (request_clients )) {
3941
3953
zend_hash_destroy (MONGODB_G (request_clients ));
3942
3954
FREE_HASHTABLE (MONGODB_G (request_clients ));
@@ -3957,20 +3969,10 @@ PHP_RSHUTDOWN_FUNCTION(mongodb)
3957
3969
/* {{{ PHP_GSHUTDOWN_FUNCTION */
3958
3970
PHP_GSHUTDOWN_FUNCTION (mongodb )
3959
3971
{
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
3964
3974
* 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 );
3974
3976
3975
3977
mongodb_globals -> debug = NULL ;
3976
3978
if (mongodb_globals -> debug_fd ) {
0 commit comments