aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPeter Eisentraut <peter_e@gmx.net>2018-05-02 16:50:03 -0400
committerPeter Eisentraut <peter_e@gmx.net>2018-05-03 08:39:15 -0400
commit30c66e77be1d890c3cca766259c0bec80bcac1b5 (patch)
treea4b27230b6a9412e58786d483220cd02b9c9bca7 /src
parenta365f52d58317e3b24e06564e1f6474ffa3221d4 (diff)
downloadpostgresql-30c66e77be1d890c3cca766259c0bec80bcac1b5.tar.gz
postgresql-30c66e77be1d890c3cca766259c0bec80bcac1b5.zip
Fix SPI error cleanup and memory leak
Since the SPI stack has been moved from TopTransactionContext to TopMemoryContext, setting _SPI_stack to NULL in AtEOXact_SPI() leaks memory. In fact, we don't need to do that anymore: We just leave the allocated stack around for the next SPI use. Also, refactor the SPI cleanup so that it is run both at transaction end and when returning to the main loop on an exception. The latter is necessary when a procedure calls a COMMIT or ROLLBACK command that itself causes an error.
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/spi.c30
-rw-r--r--src/backend/tcop/postgres.c2
-rw-r--r--src/include/executor/spi.h1
3 files changed, 19 insertions, 14 deletions
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 08f6f67a15c..22dd55c3783 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -261,34 +261,36 @@ SPI_rollback(void)
}
/*
+ * Clean up SPI state. Called on transaction end (of non-SPI-internal
+ * transactions) and when returning to the main loop on error.
+ */
+void
+SPICleanup(void)
+{
+ _SPI_current = NULL;
+ _SPI_connected = -1;
+ SPI_processed = 0;
+ SPI_lastoid = InvalidOid;
+ SPI_tuptable = NULL;
+}
+
+/*
* Clean up SPI state at transaction commit or abort.
*/
void
AtEOXact_SPI(bool isCommit)
{
- /*
- * Do nothing if the transaction end was initiated by SPI.
- */
+ /* Do nothing if the transaction end was initiated by SPI. */
if (_SPI_current && _SPI_current->internal_xact)
return;
- /*
- * Note that memory contexts belonging to SPI stack entries will be freed
- * automatically, so we can ignore them here. We just need to restore our
- * static variables to initial state.
- */
if (isCommit && _SPI_connected != -1)
ereport(WARNING,
(errcode(ERRCODE_WARNING),
errmsg("transaction left non-empty SPI stack"),
errhint("Check for missing \"SPI_finish\" calls.")));
- _SPI_current = _SPI_stack = NULL;
- _SPI_stack_depth = 0;
- _SPI_connected = -1;
- SPI_processed = 0;
- SPI_lastoid = InvalidOid;
- SPI_tuptable = NULL;
+ SPICleanup();
}
/*
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 3828cae921d..f4133953beb 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -42,6 +42,7 @@
#include "catalog/pg_type.h"
#include "commands/async.h"
#include "commands/prepare.h"
+#include "executor/spi.h"
#include "jit/jit.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
@@ -3941,6 +3942,7 @@ PostgresMain(int argc, char *argv[],
WalSndErrorCleanup();
PortalErrorCleanup();
+ SPICleanup();
/*
* We can't release replication slots inside AbortTransaction() as we
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h
index e5bdaecc4e3..143a89a16c4 100644
--- a/src/include/executor/spi.h
+++ b/src/include/executor/spi.h
@@ -163,6 +163,7 @@ extern void SPI_start_transaction(void);
extern void SPI_commit(void);
extern void SPI_rollback(void);
+extern void SPICleanup(void);
extern void AtEOXact_SPI(bool isCommit);
extern void AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid);