Skip to content

Conversation

@KentarouTakeda
Copy link
Contributor

This patch makes ext/pdo_pgsql clear session-local state when performing disconnect-equivalent processing by issuing a single DISCARD ALL on the libpq connection.

Why

Persistent PDO connections could carry session-scoped state across disconnect-equivalent lifecycles, causing surprising behavior for users (changed session settings, leftover temporary objects or prepared statements, or stuck advisory locks).

Clearing the session on disconnect-equivalent processing prevents these surprises.
ext/pgsql already performs a session reset using RESET ALL; DISCARD ALL is more comprehensive (it also releases advisory locks and removes temporary objects), so pdo_pgsql uses DISCARD ALL for broader cleanup.

Risk / Benefit

The change runs only during disconnect-equivalent cleanup and does not affect active connections. The small runtime cost of the DISCARD ALL call is outweighed by reducing hard-to-diagnose bugs caused by stale session state.

Ref

@devnexen
Copy link
Member

nice ! I may have a better look today (or Saki might) as far as statements are deallocated beforehand i.e. "DEALLOCATE " then it should be good but I surely do not know pdo_pgsql code by heart. cheers

@devnexen
Copy link
Member

nvm so DISCARD ALL already DEALLOCATE ALL according to your link. Good to know !

require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';

$pdo1 = PDOTest::test_factory(__DIR__ . '/common.phpt');

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: would it be possible to store SELECT pg_backend_pid() query before this one and the other and checking if they re equal ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added it to all the tests (now 3) related to this issue.

You were right. I was confused myself by the 3 tests, some of which keep the pid the same and some of which intentionally change it :'D

pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;

if(H->server) {
res = PQexec(H->server, "DISCARD ALL");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be nice to have a test with a transaction being interrupted, then forcing the shutdown wdyt ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a test case that "attempts to perform disconnection-equivalent processing after being disconnected from the outside." This is because session-level parameters and advisory locks have no concept of transactions.

For normal transactions, the previous implementation appears to correctly detect and initialize transactions, even if the BEGIN statement is issued independently with exec() without using beginTransaction():

return PQtransactionStatus(H->server) > PQTRANS_IDLE;

php-src/ext/pdo/pdo_dbh.c

Lines 1588 to 1591 in 1ee8dfd

if (dbh->driver_data && dbh->methods && dbh->methods->rollback && pdo_is_in_transaction(dbh)) {
dbh->methods->rollback(dbh);
dbh->in_txn = false;
}

@KentarouTakeda KentarouTakeda force-pushed the pdo-pgsql/reset-persistent-session-on-disconnect branch from 9ff988a to 1754f4c Compare November 25, 2025 00:55
->query('show log_min_duration_statement;')
->fetchColumn(0);

echo "pid1 is equals to pid2: " . (($pid1 === $pid2) ? 'yes' : 'no') . "\n";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is supposed to be yes, I would prefer then an assertion or if (...) die(...);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've switched to using assert(). I noticed other tests doing the same. Thanks for pointing that out!

Copy link
Member

@devnexen devnexen Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ll give another round of review later but I do not foresee any major concern, it will probably be ok.

@KentarouTakeda KentarouTakeda force-pushed the pdo-pgsql/reset-persistent-session-on-disconnect branch from 1754f4c to 124a1ca Compare November 25, 2025 10:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants