Dear hackers,

I found $SUBJECT when I'm playing with the single user mode.

How to reproduce
===========
You can reproduce the failure with below steps.

```
# Initialize an instance
$ initdb -D data -U postgres
# Start it as single user mode
$ postgres --single -D data/ postgres 

PostgreSQL stand-alone backend 18devel
backend> SELECT pg_create_physical_replication_slot(slot_name := 
'physical_slot', immediately_reserve := true);
...
backend> SELECT pg_replication_slot_advance('physical_slot', 
pg_current_wal_lsn());
         1: pg_replication_slot_advance (typeid = 2249, len = -1, typmod = -1, 
byval = f)
        ----
TRAP: failed Assert("slot != NULL && (slot->active_pid != 0)"), File: 
"../postgres/src/backend/replication/slot.c", Line: 674, PID: 430860
postgres(ExceptionalCondition+0xab)[0xb86a2a]
postgres(ReplicationSlotRelease+0x5a)[0x8df10b]
postgres(pg_replication_slot_advance+0x330)[0x8e46ed]
...
```

Analysis
=====
We trapped at below assertion in ReplicationSlotRelease(). IIUC, 
`slot->active_pid` is set
only when the process is under the postmaster, but ReplicationSlotRelease() 
always requires it.

```
        Assert(slot != NULL && slot->active_pid != 0);
```

Possible fix
=======

Naively considered, there are two approaches to fix this. 1) set active_pid 
when even in the single
user mode [1], or 2) ease the condition to accept the situation [2]. I'm not 
familiar with the mode,
but [1] seems better if we want to unify codes.

Thought?

[1]:
```
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -599,7 +599,7 @@ retry:
                SpinLockRelease(&s->mutex);
        }
        else
-               active_pid = MyProcPid;
+               s->active_pid = active_pid = MyProcPid;
        LWLockRelease(ReplicationSlotControlLock);
 
        /*
```
[2]:
```
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -671,7 +671,8 @@ ReplicationSlotRelease(void)
        bool            is_logical = false; /* keep compiler quiet */
        TimestampTz now = 0;
 
-       Assert(slot != NULL && slot->active_pid != 0);
+       Assert(slot != NULL &&
+                  (slot->active_pid != 0 || !IsUnderPostmaster));
 
        if (am_walsender)
        {
```

Best regards,
Hayato Kuroda
FUJITSU LIMITED



Reply via email to