]> granicus.if.org Git - postgresql/commitdiff
Properly remove ephemeral replication slots after a crash restart.
authorAndres Freund <andres@anarazel.de>
Thu, 24 Jul 2014 12:32:34 +0000 (14:32 +0200)
committerAndres Freund <andres@anarazel.de>
Thu, 24 Jul 2014 12:44:41 +0000 (14:44 +0200)
Ephemeral slots - slots that shouldn't survive database restarts -
weren't properly cleaned up after a immediate/crash restart. They were
ignored in the sense that they weren't restored into memory and thus
didn't cause unwanted resource retention; but they prevented a new
slot with the same name from being created.

Now ephemeral slots are fully removed during startup.

Backpatch to 9.4 where replication slots where added.

src/backend/replication/slot.c

index 5671ac1d14fdb4368e71a27a3cca7203106d55a0..b374c6eccf501b3f1176ad113a21b2411fd0be5b 100644 (file)
@@ -1192,6 +1192,24 @@ RestoreSlotFromDisk(const char *name)
                                (errmsg("replication slot file %s: checksum mismatch, is %u, should be %u",
                                                path, checksum, cp.checksum)));
 
+       /*
+        * If we crashed with an ephemeral slot active, don't restore but delete
+        * it.
+        */
+       if (cp.slotdata.persistency != RS_PERSISTENT)
+       {
+               sprintf(path, "pg_replslot/%s", name);
+
+               if (!rmtree(path, true))
+               {
+                       ereport(WARNING,
+                                       (errcode_for_file_access(),
+                                        errmsg("could not remove directory \"%s\"", path)));
+               }
+               fsync_fname("pg_replslot", true);
+               return;
+       }
+
        /* nothing can be active yet, don't lock anything */
        for (i = 0; i < max_replication_slots; i++)
        {
@@ -1206,10 +1224,6 @@ RestoreSlotFromDisk(const char *name)
                memcpy(&slot->data, &cp.slotdata,
                           sizeof(ReplicationSlotPersistentData));
 
-               /* Don't restore the slot if it's not parked as persistent. */
-               if (slot->data.persistency != RS_PERSISTENT)
-                       return;
-
                /* initialize in memory state */
                slot->effective_xmin = cp.slotdata.xmin;
                slot->effective_catalog_xmin = cp.slotdata.catalog_xmin;