OSDN Git Service

Run a portal's cleanup hook immediately when pushing it to DONE state.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 3 Mar 2011 18:03:34 +0000 (13:03 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 3 Mar 2011 18:04:06 +0000 (13:04 -0500)
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
src/backend/utils/mmgr/portalmem.c
src/include/utils/portal.h

index edde564..1286ede 100644 (file)
@@ -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;
index 0ca5e11..7fa66b4 100644 (file)
@@ -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.
  */
index dd88451..3068003 100644 (file)
@@ -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,