@@ -765,7 +765,14 @@ AtAbort_Portals(void)
765765 {
766766 Portal portal = hentry -> portal ;
767767
768- /* Any portal that was actually running has to be considered broken */
768+ /*
769+ * See similar code in AtSubAbort_Portals(). This would fire if code
770+ * orchestrating multiple top-level transactions within a portal, such
771+ * as VACUUM, caught errors and continued under the same portal with a
772+ * fresh transaction. No part of core PostgreSQL functions that way.
773+ * XXX Such code would wish the portal to remain ACTIVE, as in
774+ * PreCommit_Portals().
775+ */
769776 if (portal -> status == PORTAL_ACTIVE )
770777 MarkPortalFailed (portal );
771778
@@ -919,9 +926,10 @@ AtSubAbort_Portals(SubTransactionId mySubid,
919926 portal -> activeSubid = parentSubid ;
920927
921928 /*
922- * Upper-level portals that failed while running in this
923- * subtransaction must be forced into FAILED state, for the
924- * same reasons discussed below.
929+ * A MarkPortalActive() caller ran an upper-level portal in
930+ * this subtransaction and left the portal ACTIVE. This can't
931+ * happen, but force the portal into FAILED state for the same
932+ * reasons discussed below.
925933 *
926934 * We assume we can get away without forcing upper-level READY
927935 * portals to fail, even if they were run and then suspended.
@@ -961,6 +969,10 @@ AtSubAbort_Portals(SubTransactionId mySubid,
961969 * We have to do this because they might refer to objects created or
962970 * changed in the failed subtransaction, leading to crashes within
963971 * ExecutorEnd when portalcmds.c tries to close down the portal.
972+ * Currently, every MarkPortalActive() caller ensures it updates the
973+ * portal status again before relinquishing control, so ACTIVE can't
974+ * happen here. If it does happen, dispose the portal like existing
975+ * MarkPortalActive() callers would.
964976 */
965977 if (portal -> status == PORTAL_READY ||
966978 portal -> status == PORTAL_ACTIVE )
0 commit comments