@@ -939,12 +939,20 @@ static void _close_pgsql_link(zend_resource *rsrc)
939
939
{
940
940
PGconn * link = (PGconn * )rsrc -> ptr ;
941
941
PGresult * res ;
942
+ zval * hash ;
942
943
943
944
while ((res = PQgetResult (link ))) {
944
945
PQclear (res );
945
946
}
946
947
PQfinish (link );
947
948
PGG (num_links )-- ;
949
+
950
+ /* Remove connection hash for this link */
951
+ hash = zend_hash_index_find (& PGG (hashes ), (uintptr_t ) link );
952
+ if (hash ) {
953
+ zend_hash_index_del (& PGG (hashes ), (uintptr_t ) link );
954
+ zend_hash_del (& EG (regular_list ), Z_STR_P (hash ));
955
+ }
948
956
}
949
957
/* }}} */
950
958
@@ -1099,6 +1107,7 @@ static PHP_GINIT_FUNCTION(pgsql)
1099
1107
memset (pgsql_globals , 0 , sizeof (zend_pgsql_globals ));
1100
1108
/* Initilize notice message hash at MINIT only */
1101
1109
zend_hash_init_ex (& pgsql_globals -> notices , 0 , NULL , ZVAL_PTR_DTOR , 1 , 0 );
1110
+ zend_hash_init_ex (& pgsql_globals -> hashes , 0 , NULL , ZVAL_PTR_DTOR , 1 , 0 );
1102
1111
}
1103
1112
/* }}} */
1104
1113
@@ -1215,6 +1224,7 @@ PHP_MSHUTDOWN_FUNCTION(pgsql)
1215
1224
{
1216
1225
UNREGISTER_INI_ENTRIES ();
1217
1226
zend_hash_destroy (& PGG (notices ));
1227
+ zend_hash_destroy (& PGG (hashes ));
1218
1228
1219
1229
return SUCCESS ;
1220
1230
}
@@ -1236,6 +1246,7 @@ PHP_RSHUTDOWN_FUNCTION(pgsql)
1236
1246
{
1237
1247
/* clean up notice messages */
1238
1248
zend_hash_clean (& PGG (notices ));
1249
+ zend_hash_clean (& PGG (hashes ));
1239
1250
/* clean up persistent connection */
1240
1251
zend_hash_apply (& EG (persistent_list ), (apply_func_t ) _rollback_transactions );
1241
1252
return SUCCESS ;
@@ -1431,14 +1442,11 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
1431
1442
}
1432
1443
1433
1444
link = (zend_resource * )index_ptr -> ptr ;
1434
- if (link -> ptr && (link -> type == le_link || link -> type == le_plink )) {
1435
- php_pgsql_set_default_link (link );
1436
- GC_REFCOUNT (link )++ ;
1437
- RETVAL_RES (link );
1438
- goto cleanup ;
1439
- } else {
1440
- zend_hash_del (& EG (regular_list ), str .s );
1441
- }
1445
+ ZEND_ASSERT (link -> ptr && (link -> type == le_link || link -> type == le_plink ));
1446
+ php_pgsql_set_default_link (link );
1447
+ GC_REFCOUNT (link )++ ;
1448
+ RETVAL_RES (link );
1449
+ goto cleanup ;
1442
1450
}
1443
1451
if (PGG (max_links ) != -1 && PGG (num_links ) >= PGG (max_links )) {
1444
1452
php_error_docref (NULL , E_WARNING , "Cannot create new link. Too many open links (" ZEND_LONG_FMT ")" , PGG (num_links ));
@@ -1484,6 +1492,16 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
1484
1492
if (zend_hash_update_mem (& EG (regular_list ), str .s , (void * ) & new_index_ptr , sizeof (zend_resource )) == NULL ) {
1485
1493
goto err ;
1486
1494
}
1495
+
1496
+ /* Keep track of link => hash mapping, so we can remove the hash entry from regular_list
1497
+ * when the connection is closed. This uses the address of the connection rather than the
1498
+ * zend_resource, because the resource destructor is passed a stack copy of the resource
1499
+ * structure. */
1500
+ {
1501
+ zval tmp ;
1502
+ ZVAL_STR_COPY (& tmp , str .s );
1503
+ zend_hash_index_update (& PGG (hashes ), (uintptr_t ) pgsql , & tmp );
1504
+ }
1487
1505
PGG (num_links )++ ;
1488
1506
}
1489
1507
/* set notice processor */
0 commit comments