Do CHECK_FOR_INTERRUPTS inside, not before, scanGetItem.
authorTom Lane <[email protected]>
Tue, 26 Aug 2025 15:38:41 +0000 (11:38 -0400)
committerTom Lane <[email protected]>
Tue, 26 Aug 2025 15:38:41 +0000 (11:38 -0400)
The CHECK_FOR_INTERRUPTS call in gingetbitmap turns out to be
inadequate to prevent a long uninterruptible loop, because
we now know a case where looping occurs within scanGetItem.
While the next patch will fix the bug that caused that, it
seems foolish to assume that no similar patterns are possible.
Let's do the CFI within scanGetItem's retry loop, instead.
This demonstrably allows canceling out of the loop exhibited
in bug #19031.

Bug: #19031
Reported-by: Tim Wood <[email protected]>
Author: Tom Lane <[email protected]>
Discussion: https://postgr.es/m/19031-0638148643d25548@postgresql.org
Backpatch-through: 13

src/backend/access/gin/ginget.c

index f29ccd3c2d1ff31e2678a644a5277d09fb983f49..656299b1b528fac35bf4549f66844f759969e872 100644 (file)
@@ -1327,6 +1327,8 @@ scanGetItem(IndexScanDesc scan, ItemPointerData advancePast,
     */
    do
    {
+       CHECK_FOR_INTERRUPTS();
+
        ItemPointerSetMin(item);
        match = true;
        for (i = 0; i < so->nkeys && match; i++)
@@ -1966,8 +1968,6 @@ gingetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 
    for (;;)
    {
-       CHECK_FOR_INTERRUPTS();
-
        if (!scanGetItem(scan, iptr, &iptr, &recheck))
            break;