@@ -1517,6 +1517,39 @@ static mongoc_client_t *php_phongo_make_mongo_client(const mongoc_uri_t *uri, mo
1517
1517
return client ;
1518
1518
} /* }}} */
1519
1519
1520
+ static void php_phongo_persist_client (const char * hash , size_t hash_len , mongoc_client_t * client TSRMLS_DC )
1521
+ {
1522
+ php_phongo_pclient_t * pclient = (php_phongo_pclient_t * ) pecalloc (1 , sizeof (php_phongo_pclient_t ), 1 );
1523
+
1524
+ pclient -> pid = (int ) getpid ();
1525
+ pclient -> client = client ;
1526
+
1527
+ #if PHP_VERSION_ID >= 70000
1528
+ zend_hash_str_update_ptr (& MONGODB_G (pclients ), hash , hash_len , pclient );
1529
+ #else
1530
+ zend_hash_update (& MONGODB_G (pclients ), hash , hash_len + 1 , & pclient , sizeof (php_phongo_pclient_t * ), NULL );
1531
+ #endif
1532
+ }
1533
+
1534
+ static mongoc_client_t * php_phongo_find_client (const char * hash , size_t hash_len TSRMLS_DC )
1535
+ {
1536
+ #if PHP_VERSION_ID >= 70000
1537
+ php_phongo_pclient_t * pclient ;
1538
+
1539
+ if ((pclient = zend_hash_str_find_ptr (& MONGODB_G (pclients ), hash , hash_len )) != NULL ) {
1540
+ return pclient -> client ;
1541
+ }
1542
+ #else
1543
+ php_phongo_pclient_t * * pclient ;
1544
+
1545
+ if (zend_hash_find (& MONGODB_G (pclients ), hash , hash_len + 1 , (void * * ) & pclient ) == SUCCESS ) {
1546
+ return (* pclient )-> client ;
1547
+ }
1548
+ #endif
1549
+
1550
+ return NULL ;
1551
+ }
1552
+
1520
1553
void phongo_manager_init (php_phongo_manager_t * manager , const char * uri_string , zval * options , zval * driverOptions TSRMLS_DC ) /* {{{ */
1521
1554
{
1522
1555
char * hash = NULL ;
@@ -1526,30 +1559,15 @@ void phongo_manager_init(php_phongo_manager_t *manager, const char *uri_string,
1526
1559
mongoc_ssl_opt_t * ssl_opt = NULL ;
1527
1560
bson_iter_t iter ;
1528
1561
1529
- #if PHP_VERSION_ID >= 70000
1530
- mongoc_client_t * client_ptr ;
1531
- #else
1532
- mongoc_client_t * * client_ptr ;
1533
- #endif
1534
-
1535
1562
if (!(hash = php_phongo_manager_make_client_hash (uri_string , options , driverOptions , & hash_len TSRMLS_CC ))) {
1536
1563
/* Exception should already have been thrown and there is nothing to free */
1537
1564
return ;
1538
1565
}
1539
1566
1540
- #if PHP_VERSION_ID >= 70000
1541
- if ((client_ptr = zend_hash_str_find_ptr (& MONGODB_G (clients ), hash , hash_len )) != NULL ) {
1542
- MONGOC_DEBUG ("Found client for hash: %s\n" , hash );
1543
- manager -> client = client_ptr ;
1544
- goto cleanup ;
1545
- }
1546
- #else
1547
- if (zend_hash_find (& MONGODB_G (clients ), hash , hash_len + 1 , (void * * ) & client_ptr ) == SUCCESS ) {
1567
+ if ((manager -> client = php_phongo_find_client (hash , hash_len TSRMLS_CC ))) {
1548
1568
MONGOC_DEBUG ("Found client for hash: %s\n" , hash );
1549
- manager -> client = * client_ptr ;
1550
1569
goto cleanup ;
1551
1570
}
1552
- #endif
1553
1571
1554
1572
if (options ) {
1555
1573
phongo_zval_to_bson (options , PHONGO_BSON_NONE , & bson_options , NULL TSRMLS_CC );
@@ -1596,11 +1614,7 @@ void phongo_manager_init(php_phongo_manager_t *manager, const char *uri_string,
1596
1614
}
1597
1615
1598
1616
MONGOC_DEBUG ("Created client hash: %s\n" , hash );
1599
- #if PHP_VERSION_ID >= 70000
1600
- zend_hash_str_update_ptr (& MONGODB_G (clients ), hash , hash_len , manager -> client );
1601
- #else
1602
- zend_hash_update (& MONGODB_G (clients ), hash , hash_len + 1 , & manager -> client , sizeof (mongoc_client_t * ), NULL );
1603
- #endif
1617
+ php_phongo_persist_client (hash , hash_len , manager -> client TSRMLS_CC );
1604
1618
1605
1619
cleanup :
1606
1620
if (hash ) {
@@ -1835,15 +1849,26 @@ PHP_INI_BEGIN()
1835
1849
PHP_INI_END ()
1836
1850
/* }}} */
1837
1851
1852
+ static inline void php_phongo_pclient_destroy (php_phongo_pclient_t * pclient )
1853
+ {
1854
+ /* Do not destroy mongoc_client_t objects created by other processes. This
1855
+ * ensures that we do not shutdown sockets that may still be in use by our
1856
+ * parent process (see: CDRIVER-2049). While this is a leak, we are already
1857
+ * in MSHUTDOWN at this point. */
1858
+ if (pclient -> pid == getpid ()) {
1859
+ mongoc_client_destroy (pclient -> client );
1860
+ }
1861
+ }
1862
+
1838
1863
#if PHP_VERSION_ID >= 70000
1839
- static void php_phongo_client_dtor (zval * zv )
1864
+ static void php_phongo_pclient_dtor (zval * zv )
1840
1865
{
1841
- mongoc_client_destroy (( mongoc_client_t * ) Z_PTR_P (zv ));
1866
+ php_phongo_pclient_destroy (( php_phongo_pclient_t * ) Z_PTR_P (zv ));
1842
1867
}
1843
1868
#else
1844
- static void php_phongo_client_dtor (void * client )
1869
+ static void php_phongo_pclient_dtor (void * pp )
1845
1870
{
1846
- mongoc_client_destroy (* ((mongoc_client_t * * ) client ));
1871
+ php_phongo_pclient_destroy (* ((php_phongo_pclient_t * * ) pp ));
1847
1872
}
1848
1873
#endif
1849
1874
@@ -1864,7 +1889,7 @@ PHP_GINIT_FUNCTION(mongodb)
1864
1889
memset (mongodb_globals , 0 , sizeof (zend_mongodb_globals ));
1865
1890
mongodb_globals -> bsonMemVTable = bsonMemVTable ;
1866
1891
/* Initialize HashTable for persistent clients */
1867
- zend_hash_init_ex (& mongodb_globals -> clients , 0 , NULL , php_phongo_client_dtor , 1 , 0 );
1892
+ zend_hash_init_ex (& mongodb_globals -> pclients , 0 , NULL , php_phongo_pclient_dtor , 1 , 0 );
1868
1893
}
1869
1894
/* }}} */
1870
1895
@@ -1994,8 +2019,8 @@ PHP_MSHUTDOWN_FUNCTION(mongodb)
1994
2019
(void )type ; /* We don't care if we are loaded via dl() or extension= */
1995
2020
1996
2021
/* Destroy HashTable for persistent clients. The HashTable destructor will
1997
- * destroy any mongoc_client_t objects contained within . */
1998
- zend_hash_destroy (& MONGODB_G (clients ));
2022
+ * destroy any mongoc_client_t objects that were created by this process . */
2023
+ zend_hash_destroy (& MONGODB_G (pclients ));
1999
2024
2000
2025
bson_mem_restore_vtable ();
2001
2026
/* Cleanup after libmongoc */
0 commit comments