From d9b5ddb3cb0cfb55d418a09f571a78ee069eb3e1 Mon Sep 17 00:00:00 2001
From: Paul Kim <mok03127@gmail.com>
Date: Sun, 19 Jul 2026 23:08:12 +0900
Subject: [PATCH v1] Restore vacuum_delay_point() in GIN posting-tree leaf
 vacuum

Commit fd83c83d094 turned the recursive posting-tree cleanup in
ginVacuumPostingTreeLeaves() into an iterative sweep that follows the
tree's leaf pages via their rightlinks.  The recursive version called
vacuum_delay_point() while processing the tree, but that call was removed
and never re-added to the new loop.  As that commit only set out to fix a
deadlock, the removal appears to have been unintentional.

Consequently the leaf-page sweep of a single posting tree runs with no
vacuum_delay_point(), and therefore no CHECK_FOR_INTERRUPTS().  A posting
tree stores all the TIDs for one indexed key, so for a frequently-occurring
key it can span a large number of leaf pages.  While such a tree is being
vacuumed the operation ignores vacuum_cost_delay and does not respond to
query cancellation or statement_timeout; an autovacuum worker likewise
cannot be interrupted mid-sweep when another backend requests a conflicting
lock.  A corrupted rightlink that forms a cycle makes the loop run
uninterruptibly forever.

Restore the call, placed after the current page has been unlocked and
released so that no buffer content lock is held across a potential delay
(cf. 21c27af65fb).  The sibling loops in ginbulkdelete() and
ginvacuumcleanup() already call vacuum_delay_point() once per page.

Back-patch to all supported branches, which all contain fd83c83d094.
---
 src/backend/access/gin/ginvacuum.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c
index 840543eb664..a0b81a215a9 100644
--- a/src/backend/access/gin/ginvacuum.c
+++ b/src/backend/access/gin/ginvacuum.c
@@ -429,6 +429,8 @@ ginVacuumPostingTreeLeaves(GinVacuumState *gvs, BlockNumber blkno)
 		if (blkno == InvalidBlockNumber)
 			break;
 
+		vacuum_delay_point(false);
+
 		buffer = ReadBufferExtended(gvs->index, MAIN_FORKNUM, blkno,
 									RBM_NORMAL, gvs->strategy);
 		LockBuffer(buffer, GIN_EXCLUSIVE);
-- 
2.50.1 (Apple Git-155)

