From 8571a061e7c68708d37d60b964136bd727789fdb Mon Sep 17 00:00:00 2001 From: sam marshall Date: Thu, 29 Aug 2019 10:47:09 +0100 Subject: [PATCH] MDL-63315 DB: Postgres - Clear cursors in persistent connection If there is a PHP fatal error and destructors do not run (this can happen in out-of-memory errors, and maybe if there is an error in a previous destructor) then Postgres cursors may be left open. Usually this does not cause a problem because the connection is closed anyway, but if using persistent connections, a future request may reuse the connection with a cursor open. It then gets errors when it tries to create a new cursor with the same name. This change closes all cursors at the start of a persistent connection. --- lib/dml/pgsql_native_moodle_database.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/dml/pgsql_native_moodle_database.php b/lib/dml/pgsql_native_moodle_database.php index 97d94905ff9..5d0ddb5944b 100644 --- a/lib/dml/pgsql_native_moodle_database.php +++ b/lib/dml/pgsql_native_moodle_database.php @@ -187,6 +187,17 @@ class pgsql_native_moodle_database extends moodle_database { throw new dml_connection_exception($dberr); } + if (!empty($this->dboptions['dbpersist'])) { + // There are rare situations (such as PHP out of memory errors) when open cursors may + // not be closed at the end of a connection. When using persistent connections, the + // cursors remain open and 'get in the way' of future connections. To avoid this + // problem, close all cursors here. + $result = pg_query($this->pgsql, 'CLOSE ALL'); + if ($result) { + pg_free_result($result); + } + } + if (!empty($this->dboptions['dbhandlesoptions'])) { /* We don't trust people who just set the dbhandlesoptions, this code checks up on them. * These functions do not talk to the server, they use the client library knowledge to determine state.