Re: Startup process deadlock: WaitForProcSignalBarriers vs aux process
Masahiko Sawada <sawada.mshk@gmail.com>
From: Masahiko Sawada <sawada.mshk@gmail.com>
To: Alexander Lakhin <exclusion@gmail.com>
Cc: Andres Freund <andres@anarazel.de>, Matthias van de Meent <boekewurm+postgres@gmail.com>,
Thomas Munro <thomas.munro@gmail.com>, PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>,
Heikki Linnakangas <hlinnaka@iki.fi>
Date: 2026-04-28T19:27:59Z
Lists: pgsql-hackers
Attachments
- v1-0001-Fix-race-between-ProcSignalInit-and-EmitProcSigna.patch (text/x-patch) patch v1-0001
On Mon, Apr 27, 2026 at 11:00 AM Alexander Lakhin <exclusion@gmail.com> wrote: > > Hello Sawada-san, > > 24.04.2026 20:52, Masahiko Sawada wrote: > > Right. The postmaster blocks all signals before starting child process > as the following comment explains: > > /* > * We start postmaster children with signals blocked. This allows them to > * install their own handlers before unblocking, to avoid races where they > * might run the postmaster's handler and miss an important control > * signal. With more analysis this could potentially be relaxed. > */ > sigprocmask(SIG_SETMASK, &BlockSig, &save_mask); > > Investigating the issue, I found there is a race condition between the > procsignal initialization and emitting signal barrier that could be > the cause of this issue. Imagine the following scenario: > > 1. In ProcSignalInit(), the checkpointer initializes its > slot->pss_barrierGeneration with the global generation. > 2. In EmitProcSignalBarrier(), the startup checks the checkpointer's > procsignal slot but it skips emitting the signal as slot->pss_pid is > still 0. It can happen even though the checkpointer holds a spinlock > on its slot during the initialization because the first pid check is > done without a spinlock acquisition. > 3. The checkpointer sets its pid to slot->pss_pid and releases the spin lock. > 4. In WaitForProcSignalBarrier(), the startup checks the > checkpointer's procsignal slot that has already initialized the > pss_barrierGeneration, and waits for it to be updated. However, the > checkpointer never updates its barrier generation as it doesn't get > the signal. > > > Thank you for the investigation and explanation of the issue! > > I've been puzzled by a buildfarm failure [1] with such symptoms for a while > and even reproduced it locally once, but couldn't gather more information > that time. But now that you have described the scenario, I can easily > reproduce the same test failure with: > --- a/src/backend/storage/ipc/procsignal.c > +++ b/src/backend/storage/ipc/procsignal.c > @@ -206,6 +206,7 @@ ProcSignalInit(const uint8 *cancel_key, int cancel_key_len) > if (cancel_key_len > 0) > memcpy(slot->pss_cancel_key, cancel_key, cancel_key_len); > slot->pss_cancel_key_len = cancel_key_len; > +pg_usleep(10000); > pg_atomic_write_u32(&slot->pss_pid, MyProcPid); Thank you for testing this. I've attached a patch to address the issue. I haven't verified it across all versions yet, but I suspect it exists in the stable branches as well. Previously, the issue rarely occurred because EmitProcSignalBarrier() was only used for smgr invalidation. However, now that we use signal barriers for online wal_level changes and checksum status updates, this race condition is likely to be encountered more frequently. Regards, -- Masahiko Sawada Amazon Web Services: https://aws.amazon.com
Commits
Same data as JSON:
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Fix race between ProcSignalInit() and EmitProcSignalBarrier().
- 159324a73a39 15 (unreleased) landed
- cdb9b2830d48 16 (unreleased) landed
- a651b8a89e7f 17 (unreleased) landed
- 1a9b1cc18e06 18 (unreleased) landed
- d79bf7612a07 19 (unreleased) landed
-
Fix race condition in XLogLogicalInfo and ProcSignal initialization.
- b384cdb2745b 19 (unreleased) landed