[php-src] master: ext/pdo: persistent_shutdown run while the connection is still shared.
| From: | David Carlier | Date: | Thu, 22 Oct 2026 11:15:01 +0000 |
| Subject: | [php-src] master: ext/pdo: persistent_shutdown run while the connection is still shared. | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-142557@lists.php.net to get a copy of this message | ||
Author: David Carlier (devnexen)
Date: 2026-10-22T12:05:15+01:00
Commit: https://github.com/php/php-src/commit/a9138d768ad1760ad87308b5fcadd532bba29b05
Raw diff: https://github.com/php/php-src/commit/a9138d768ad1760ad87308b5fcadd532bba29b05.diff
ext/pdo: persistent_shutdown run while the connection is still shared.
Only call it for the last PDO object, like the rollback before it.
Changed paths:
A ext/pdo_pgsql/tests/gh24461_shared_connection.phpt
M ext/pdo/pdo_dbh.c
Diff:
diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c
index 58bb3b1727f6..9ccaebd5e8bb 100644
--- a/ext/pdo/pdo_dbh.c
+++ b/ext/pdo/pdo_dbh.c
@@ -1606,7 +1606,7 @@ static void pdo_dbh_free_storage(zend_object *std)
dbh->in_txn = false;
}
- if (dbh->is_persistent && dbh->driver_data && dbh->methods &&
dbh->methods->persistent_shutdown) {
+ if (dbh->is_persistent && dbh->refcount <= 2 && dbh->driver_data
&& dbh->methods && dbh->methods->persistent_shutdown) {
dbh->methods->persistent_shutdown(dbh);
}
zend_object_std_dtor(std);
diff --git a/ext/pdo_pgsql/tests/gh24461_shared_connection.phpt
b/ext/pdo_pgsql/tests/gh24461_shared_connection.phpt
new file mode 100644
index 000000000000..f341beecb081
--- /dev/null
+++ b/ext/pdo_pgsql/tests/gh24461_shared_connection.phpt
@@ -0,0 +1,46 @@
+--TEST--
+GH-24461 (Persistent connections: session state is not reset while another PDO object still uses
the connection)
+--EXTENSIONS--
+pdo_pgsql
+--SKIPIF--
+<?php
+require __DIR__ . '/config.inc';
+require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+putenv('PDOTEST_ATTR='.serialize([PDO::ATTR_PERSISTENT => true]));
+
+require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
+
+$pdo1 = PDOTest::test_factory(__DIR__ . '/common.phpt');
+$pdo2 = PDOTest::test_factory(__DIR__ . '/common.phpt');
+
+$pid1 = (int) $pdo1->query('SELECT pg_backend_pid()')->fetchColumn();
+$pid2 = (int) $pdo2->query('SELECT pg_backend_pid()')->fetchColumn();
+var_dump($pid1 === $pid2);
+
+$pdo2->exec("SET application_name = 'gh24461'");
+$pdo2->exec('CREATE TEMP TABLE gh24461_shared (i int)');
+$pdo2->query('SELECT pg_advisory_lock(24461)');
+$stmt = $pdo2->prepare('SELECT 42');
+$stmt->execute();
+$stmt->closeCursor();
+
+$pdo1 = null;
+
+var_dump($pdo2->query('SHOW application_name')->fetchColumn());
+var_dump($pdo2->query('SELECT count(*) FROM gh24461_shared')->fetchColumn());
+var_dump($pdo2->query("SELECT count(*) FROM pg_locks WHERE locktype = 'advisory'
AND objid = 24461 AND pid = pg_backend_pid()")->fetchColumn());
+$stmt->execute();
+var_dump($stmt->fetchColumn());
+
+$pdo2->query('SELECT pg_advisory_unlock_all()');
+?>
+--EXPECT--
+bool(true)
+string(7) "gh24461"
+string(1) "0"
+string(1) "1"
+string(2) "42"