From 6252c4f9e201f619e5eebda12fa867acd4e4200e Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 3 Mar 2011 13:03:34 -0500 Subject: [PATCH] Run a portal's cleanup hook immediately when pushing it to DONE state. This works around the problem noted by Yamamoto Takashi in bug #5906, that there were code paths whereby we could reach AtCleanup_Portals with a portal's cleanup hook still unexecuted. The changes I made a few days ago were intended to prevent that from happening, and I think that on balance it's still a good thing to avoid, so I don't want to remove the Assert in AtCleanup_Portals. Hence do this instead. --- src/backend/tcop/pquery.c | 2 +- src/backend/utils/mmgr/portalmem.c | 26 ++++++++++++++++++++++++++ src/include/utils/portal.h | 1 + 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index edde5642ee..1286edee72 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -814,7 +814,7 @@ PortalRun(Portal portal, long count, bool isTopLevel, dest, altdest, completionTag); /* Prevent portal's commands from being re-executed */ - portal->status = PORTAL_DONE; + MarkPortalDone(portal); /* Always complete at end of RunMulti */ result = true; diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index 0ca5e11039..7fa66b4221 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -402,6 +402,32 @@ UnpinPortal(Portal portal) } /* + * MarkPortalDone + * Transition a portal from ACTIVE to DONE state. + */ +void +MarkPortalDone(Portal portal) +{ + /* Perform the state transition */ + Assert(portal->status == PORTAL_ACTIVE); + portal->status = PORTAL_DONE; + + /* + * Allow portalcmds.c to clean up the state it knows about. We might + * as 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 from reaching + * AtCleanup_Portals with the cleanup hook still unexecuted. + */ + if (PointerIsValid(portal->cleanup)) + { + (*portal->cleanup) (portal); + portal->cleanup = NULL; + } +} + +/* * PortalDrop * Destroy the portal. */ diff --git a/src/include/utils/portal.h b/src/include/utils/portal.h index dd88451f95..3068003caa 100644 --- a/src/include/utils/portal.h +++ b/src/include/utils/portal.h @@ -206,6 +206,7 @@ extern Portal CreatePortal(const char *name, bool allowDup, bool dupSilent); extern Portal CreateNewPortal(void); extern void PinPortal(Portal portal); extern void UnpinPortal(Portal portal); +extern void MarkPortalDone(Portal portal); extern void PortalDrop(Portal portal, bool isTopCommit); extern Portal GetPortalByName(const char *name); extern void PortalDefineQuery(Portal portal, -- 2.11.0