diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index a53673c..c840aa6 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -765,7 +765,14 @@ AtAbort_Portals(void) { Portal portal = hentry->portal; - /* Any portal that was actually running has to be considered broken */ + /* + * See similar code in AtSubAbort_Portals(). This would fire if code + * orchestrating multiple top-level transactions within a portal, such + * as VACUUM, caught errors and continued under the same portal with a + * fresh transaction. No part of core PostgreSQL functions that way. + * XXX Such code would wish the portal to remain ACTIVE, as in + * PreCommit_Portals(). + */ if (portal->status == PORTAL_ACTIVE) MarkPortalFailed(portal); @@ -919,9 +926,11 @@ AtSubAbort_Portals(SubTransactionId mySubid, portal->activeSubid = parentSubid; /* - * Upper-level portals that failed while running in this - * subtransaction must be forced into FAILED state, for the - * same reasons discussed below. + * If a bug in a MarkPortalActive() caller has it miss cleanup + * after having failed while running an upper-level portal in + * this subtransaction, we don't know what else in the portal + * is wrong. Force it into FAILED state, for the same reasons + * discussed below. * * We assume we can get away without forcing upper-level READY * portals to fail, even if they were run and then suspended. @@ -960,7 +969,11 @@ AtSubAbort_Portals(SubTransactionId mySubid, * Force any live portals of my own subtransaction into FAILED state. * We have to do this because they might refer to objects created or * changed in the failed subtransaction, leading to crashes within - * ExecutorEnd when portalcmds.c tries to close down the portal. + * ExecutorEnd when portalcmds.c tries to close down the portal. Each + * MarkPortalActive() caller ensures it updates the portal status + * again before relinquishing control, so ACTIVE can't happen here. + * If a bug does make it happen, dispose the portal like a normal + * MarkPortalActive() caller would. */ if (portal->status == PORTAL_READY || portal->status == PORTAL_ACTIVE)