Re: REPACK (CONCURRENTLY) backend waits indefinitely when decoding worker fails to start

From: Antonin Houska <ah(at)cybertec(dot)at>
To: Nikolay Samokhvalov <nik(at)postgres(dot)ai>
Cc: Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, Masahiko Sawada <sawada(dot)mshk(at)gmail(dot)com>, Nathan Bossart <nathandbossart(at)gmail(dot)com>, PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>, alvherre(at)kurilemu(dot)de
Subject: Re: REPACK (CONCURRENTLY) backend waits indefinitely when decoding worker fails to start
Date: 2026-09-15 10:26:40
Message-ID: 26324.1789468000@localhost
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Nikolay Samokhvalov <nik(at)postgres(dot)ai> wrote:

> On Mon, Sep 14, 2026 at 2:00 AM Antonin Houska <ah(at)cybertec(dot)at> wrote:
> > I'm not sure this should be considered a bug. AFAICS the problem happens
> > due to calling proc_exit() directly, i.e. exiting the worker w/o sending a
> > message via the error queue. (If an error was sent,
> > ConditionVariableSleep() should process it and raise ERROR in the backend
> > running REPACK.)
> >
> > However, the REPACK worker does not call proc_exit() directly.
>
> Yes, agreed: the direct proc_exit() test alone didn't establish a bug. I
> checked whether error delivery can actually fail after attachment.
>
> There is a path in mq_putmessage(): an interrupt while blocked on the full
> error queue makes recursive FATAL output detach it via pq_mq_busy. The FATAL
> reaches the server log, but not the REPACK backend.
>
> I reproduced this on v4 plus only the attached repack_worker.c test hooks,
> built with injection points and server-wide client_min_messages=debug1:
>
> 1. For queue_t with a primary key, attach the standard wait action:
>
> create extension injection_points;
> select injection_points_attach(
> 'repack-worker-before-snapshot-export', 'wait');
>
> 2. In another session run repack (concurrently) queue_t. When the worker waits
> at InjectionPoint/repack-worker-before-snapshot-export, SIGSTOP the REPACK
> backend and run:
>
> select injection_points_wakeup(
> 'repack-worker-before-snapshot-export');
>
> 3. Repeat until the worker waits at IPC/MessageQueuePutMessage:
>
> select pg_logical_emit_message(false, 'repack-queue-test',
> repeat('x', 15 * 1024 * 1024));
>
> 4. Run select pg_terminate_backend(worker_pid), wait for the worker to exit,
> then SIGCONT the REPACK backend.
>

I wonder if you forgot to attach some files (I don't see the queue_t table in
the scripts you posted earlier), but I think I was able to reproduce the
problem using the instructions above.

IMO the problem is that the backend ignores the SHM_MQ_DETACHED state in
ProcessRepackMessages(). If all the messages in the queue have severity lower
than ERROR, the worker just processes them and continues waiting for the
worker to export the snapshot. However, as the worker is gone, there's no way
to wake the backend up.

Patch 0002 in [1] should fix that.

[1] https://www.postgresql.org/message-id/CALj2ACWJsOG0-2SQUxBXG9ULFs_GJpeVhhmp8AHf8c9iKDjMXA%40mail.gmail.com

Thanks for testing!

--
Antonin Houska
Web: https://www.cybertec-postgresql.com

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Amit Kapila 2026-09-15 10:35:20 Re: Distinguish publication exclusions in object addresses
Previous Message Andrei Lepikhov 2026-09-15 09:59:56 Re: Do not scan index in right table if condition for left join evaluates to false using columns in left table