Skip to content

ext/pdo: Fix GC freeing callbacks of a shared persistent connection - #440

Closed
iliaal wants to merge 1 commit into
PHP-8.4from
fix/pdo-persistent-shared-gc
Closed

iliaal wants to merge 1 commit into
PHP-8.4from
fix/pdo-persistent-shared-gc

Conversation

@iliaal

@iliaal iliaal commented Oct 21, 2026

Copy link
Copy Markdown
Owner

Every PDO object attached to a persistent connection shares one pdo_dbh_t, and dbh_get_gc() reported the driver's GC data once per object. pdo_sqlite holds each user function, aggregate and collation callback once, so two Pdo\Sqlite::connect() calls with ATTR_PERSISTENT on the same DSN, each registering a method as a UDF, make the collector count two references for one and free closures still in use: the next query fails or crashes, and debug builds assert in zend_gc_delref. This has been the case since driver GC data was added in 8.1.

Driver GC data is now reported only while a single object owns the handle, the check the rollback guard got for phpGH-23962. While the connection is shared, cycles through those callbacks wait for request shutdown, which is already what happens with GC disabled; that is also why the test unsets the handles at the end. Functions, aggregates and collations go through the same call and were each checked, and no other bundled driver implements get_gc.

Found while testing php#24041; verified on a PHP-8.4 debug NTS build with the test red before and green after, plus valgrind memcheck on the patched build.

Every PDO object attached to a persistent connection shares one pdo_dbh_t,
and dbh_get_gc() reported the driver's GC data once per object. pdo_sqlite
holds each user function, aggregate and collation callback once, so with
two or more objects the collector subtracted more references than exist
and freed live closures, crashing or returning wrong results. Report driver
GC data only while a single object owns the handle, the same refcount check
the rollback guard uses since phpGH-23962. While the connection is shared,
cycles through those callbacks are left to request shutdown, as they already
are with GC disabled. No other bundled driver implements get_gc.
@iliaal

iliaal commented Oct 22, 2026

Copy link
Copy Markdown
Owner Author

Promoted to php#24529.

@iliaal iliaal closed this Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant