aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xact.c23
-rw-r--r--src/backend/utils/mmgr/portalmem.c30
2 files changed, 44 insertions, 9 deletions
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index a8fbd043ae5..5e7e8122003 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -4226,6 +4226,9 @@ AbortOutOfAnyTransaction(void)
{
TransactionState s = CurrentTransactionState;
+ /* Ensure we're not running in a doomed memory context */
+ AtAbort_Memory();
+
/*
* Get out of any transaction or nested transaction
*/
@@ -4267,7 +4270,14 @@ AbortOutOfAnyTransaction(void)
break;
case TBLOCK_ABORT:
case TBLOCK_ABORT_END:
- /* AbortTransaction already done, still need Cleanup */
+
+ /*
+ * AbortTransaction is already done, still need Cleanup.
+ * However, if we failed partway through running ROLLBACK,
+ * there will be an active portal running that command, which
+ * we need to shut down before doing CleanupTransaction.
+ */
+ AtAbort_Portals();
CleanupTransaction();
s->blockState = TBLOCK_DEFAULT;
break;
@@ -4290,6 +4300,14 @@ AbortOutOfAnyTransaction(void)
case TBLOCK_SUBABORT_END:
case TBLOCK_SUBABORT_RESTART:
/* As above, but AbortSubTransaction already done */
+ if (s->curTransactionOwner)
+ {
+ /* As in TBLOCK_ABORT, might have a live portal to zap */
+ AtSubAbort_Portals(s->subTransactionId,
+ s->parent->subTransactionId,
+ s->curTransactionOwner,
+ s->parent->curTransactionOwner);
+ }
CleanupSubTransaction();
s = CurrentTransactionState; /* changed by pop */
break;
@@ -4298,6 +4316,9 @@ AbortOutOfAnyTransaction(void)
/* Should be out of all subxacts now */
Assert(s->parent == NULL);
+
+ /* If we didn't actually have anything to do, revert to TopMemoryContext */
+ AtCleanup_Memory();
}
/*
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index 5983aedb121..369e1817093 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -415,8 +415,8 @@ MarkPortalDone(Portal portal)
* well do that now, since the portal can't be executed any more.
*
* In some cases involving execution of a ROLLBACK command in an already
- * aborted transaction, this prevents an assertion failure caused by
- * reaching AtCleanup_Portals with the cleanup hook still unexecuted.
+ * aborted transaction, this is necessary, or we'd reach AtCleanup_Portals
+ * with the cleanup hook still unexecuted.
*/
if (PointerIsValid(portal->cleanup))
{
@@ -443,8 +443,8 @@ MarkPortalFailed(Portal portal)
* well do that now, since the portal can't be executed any more.
*
* In some cases involving cleanup of an already aborted transaction, this
- * prevents an assertion failure caused by reaching AtCleanup_Portals with
- * the cleanup hook still unexecuted.
+ * is necessary, or we'd reach AtCleanup_Portals with the cleanup hook
+ * still unexecuted.
*/
if (PointerIsValid(portal->cleanup))
{
@@ -842,8 +842,15 @@ AtCleanup_Portals(void)
if (portal->portalPinned)
portal->portalPinned = false;
- /* We had better not be calling any user-defined code here */
- Assert(portal->cleanup == NULL);
+ /*
+ * We had better not call any user-defined code during cleanup, so if
+ * the cleanup hook hasn't been run yet, too bad; we'll just skip it.
+ */
+ if (PointerIsValid(portal->cleanup))
+ {
+ elog(WARNING, "skipping cleanup for portal \"%s\"", portal->name);
+ portal->cleanup = NULL;
+ }
/* Zap it. */
PortalDrop(portal, false);
@@ -1026,8 +1033,15 @@ AtSubCleanup_Portals(SubTransactionId mySubid)
if (portal->portalPinned)
portal->portalPinned = false;
- /* We had better not be calling any user-defined code here */
- Assert(portal->cleanup == NULL);
+ /*
+ * We had better not call any user-defined code during cleanup, so if
+ * the cleanup hook hasn't been run yet, too bad; we'll just skip it.
+ */
+ if (PointerIsValid(portal->cleanup))
+ {
+ elog(WARNING, "skipping cleanup for portal \"%s\"", portal->name);
+ portal->cleanup = NULL;
+ }
/* Zap it. */
PortalDrop(portal, false);