summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-04-10 12:23:01 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-04-10 12:23:01 +0200
commit2191eac3b3c4b393235e126e84aac9eaae230c2d (patch)
treeea88364b875f8e005dfaf99a0868d9cb258b29e9
parent231fecee273fe8a2f0570cf58b18fa149a9cd0fa (diff)
parent6615b9c287963730fcc6fdf0f49d2597154e40f9 (diff)
downloadphp-git-2191eac3b3c4b393235e126e84aac9eaae230c2d.tar.gz
Merge branch 'PHP-7.3' into PHP-7.4
-rw-r--r--Zend/zend_hash.c2
-rw-r--r--ext/pgsql/pgsql.c34
-rw-r--r--ext/pgsql/php_pgsql.h1
-rw-r--r--ext/pgsql/tests/connect_after_close.phpt19
4 files changed, 47 insertions, 9 deletions
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index f95034a60f..36d8ecf15d 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -64,7 +64,7 @@ static void _zend_is_inconsistent(const HashTable *ht, const char *file, int lin
zend_output_debug_string(1, "%s(%d) : ht=%p is inconsistent", file, line, ht);
break;
}
- zend_bailout();
+ ZEND_ASSERT(0);
}
#define IS_CONSISTENT(a) _zend_is_inconsistent(a, __FILE__, __LINE__);
#define SET_INCONSISTENT(n) do { \
diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
index ee6c952fec..a4d8fd7396 100644
--- a/ext/pgsql/pgsql.c
+++ b/ext/pgsql/pgsql.c
@@ -936,12 +936,20 @@ static void _close_pgsql_link(zend_resource *rsrc)
{
PGconn *link = (PGconn *)rsrc->ptr;
PGresult *res;
+ zval *hash;
while ((res = PQgetResult(link))) {
PQclear(res);
}
PQfinish(link);
PGG(num_links)--;
+
+ /* Remove connection hash for this link */
+ hash = zend_hash_index_find(&PGG(hashes), (uintptr_t) link);
+ if (hash) {
+ zend_hash_index_del(&PGG(hashes), (uintptr_t) link);
+ zend_hash_del(&EG(regular_list), Z_STR_P(hash));
+ }
}
/* }}} */
@@ -1095,6 +1103,7 @@ static PHP_GINIT_FUNCTION(pgsql)
memset(pgsql_globals, 0, sizeof(zend_pgsql_globals));
/* Initialize notice message hash at MINIT only */
zend_hash_init_ex(&pgsql_globals->notices, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
+ zend_hash_init_ex(&pgsql_globals->hashes, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
}
/* }}} */
@@ -1229,6 +1238,7 @@ PHP_MSHUTDOWN_FUNCTION(pgsql)
{
UNREGISTER_INI_ENTRIES();
zend_hash_destroy(&PGG(notices));
+ zend_hash_destroy(&PGG(hashes));
return SUCCESS;
}
@@ -1250,6 +1260,7 @@ PHP_RSHUTDOWN_FUNCTION(pgsql)
{
/* clean up notice messages */
zend_hash_clean(&PGG(notices));
+ zend_hash_clean(&PGG(hashes));
/* clean up persistent connection */
zend_hash_apply(&EG(persistent_list), (apply_func_t) _rollback_transactions);
return SUCCESS;
@@ -1440,14 +1451,11 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
}
link = (zend_resource *)index_ptr->ptr;
- if (link->ptr && (link->type == le_link || link->type == le_plink)) {
- php_pgsql_set_default_link(link);
- GC_ADDREF(link);
- RETVAL_RES(link);
- goto cleanup;
- } else {
- zend_hash_del(&EG(regular_list), str.s);
- }
+ ZEND_ASSERT(link->ptr && (link->type == le_link || link->type == le_plink));
+ php_pgsql_set_default_link(link);
+ GC_ADDREF(link);
+ RETVAL_RES(link);
+ goto cleanup;
}
if (PGG(max_links) != -1 && PGG(num_links) >= PGG(max_links)) {
php_error_docref(NULL, E_WARNING, "Cannot create new link. Too many open links (" ZEND_LONG_FMT ")", PGG(num_links));
@@ -1491,6 +1499,16 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
new_index_ptr.ptr = (void *) Z_RES_P(return_value);
new_index_ptr.type = le_index_ptr;
zend_hash_update_mem(&EG(regular_list), str.s, (void *) &new_index_ptr, sizeof(zend_resource));
+
+ /* Keep track of link => hash mapping, so we can remove the hash entry from regular_list
+ * when the connection is closed. This uses the address of the connection rather than the
+ * zend_resource, because the resource destructor is passed a stack copy of the resource
+ * structure. */
+ {
+ zval tmp;
+ ZVAL_STR_COPY(&tmp, str.s);
+ zend_hash_index_update(&PGG(hashes), (uintptr_t) pgsql, &tmp);
+ }
PGG(num_links)++;
}
/* set notice processor */
diff --git a/ext/pgsql/php_pgsql.h b/ext/pgsql/php_pgsql.h
index 71d6bd3de2..b8365d659a 100644
--- a/ext/pgsql/php_pgsql.h
+++ b/ext/pgsql/php_pgsql.h
@@ -317,6 +317,7 @@ ZEND_BEGIN_MODULE_GLOBALS(pgsql)
int ignore_notices,log_notices;
HashTable notices; /* notice message for each connection */
zend_resource *default_link; /* default link when connection is omitted */
+ HashTable hashes; /* hashes for each connection */
ZEND_END_MODULE_GLOBALS(pgsql)
ZEND_EXTERN_MODULE_GLOBALS(pgsql)
diff --git a/ext/pgsql/tests/connect_after_close.phpt b/ext/pgsql/tests/connect_after_close.phpt
new file mode 100644
index 0000000000..65f954570b
--- /dev/null
+++ b/ext/pgsql/tests/connect_after_close.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Reopen connection after it was closed
+--SKIPIF--
+<?php include("skipif.inc"); ?>
+--FILE--
+<?php
+include('config.inc');
+
+/* Run me under valgrind */
+$db1 = pg_connect($conn_str);
+unset($db1);
+var_dump(pg_close());
+$db2 = pg_connect($conn_str);
+unset($db2);
+var_dump(pg_close());
+?>
+--EXPECT--
+bool(true)
+bool(true)