]> granicus.if.org Git - postgresql/commitdiff
Fix assertion failure at end of PITR.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 28 Nov 2014 07:23:41 +0000 (09:23 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 28 Nov 2014 07:31:53 +0000 (09:31 +0200)
InitXLogInsert() cannot be called in a critical section, because it
allocates memory. But CreateCheckPoint() did that, when called for the
end-of-recovery checkpoint by the startup process.

In the passing, fix the scratch space allocation in InitXLogInsert to go to
the right memory context. Also update the comment at InitXLOGAccess, which
hasn't been totally accurate since hot standby was introduced (in a hot
standby backend, InitXLOGAccess isn't called at backend startup).

Reported by Michael Paquier

src/backend/access/transam/xlog.c
src/backend/access/transam/xloginsert.c

index 0f661f5010c7685282afb892ee17b300c5e9b4bc..a2ad5ebfe82b1d0287ad200a10b990862dc4c6c0 100644 (file)
@@ -7254,10 +7254,9 @@ ReadCheckpointRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr,
 }
 
 /*
- * This must be called during startup of a backend process, except that
- * it need not be called in a standalone backend (which does StartupXLOG
- * instead).  We need to initialize the local copies of ThisTimeLineID and
- * RedoRecPtr.
+ * This must be called in a backend process before creating WAL records
+ * (except in a standalone backend, which does StartupXLOG instead).  We need
+ * to initialize the local copies of ThisTimeLineID and RedoRecPtr.
  *
  * Note: before Postgres 8.0, we went to some effort to keep the postmaster
  * process's copies of ThisTimeLineID and RedoRecPtr valid too.  This was
@@ -7594,6 +7593,16 @@ CreateCheckPoint(int flags)
        if (RecoveryInProgress() && (flags & CHECKPOINT_END_OF_RECOVERY) == 0)
                elog(ERROR, "can't create a checkpoint during recovery");
 
+       /*
+        * Initialize InitXLogInsert working areas before entering the critical
+        * section.  Normally, this is done by the first call to
+        * RecoveryInProgress() or LocalSetXLogInsertAllowed(), but when creating
+        * an end-of-recovery checkpoint, the LocalSetXLogInsertAllowed call is
+        * done below in a critical section, and InitXLogInsert cannot be called
+        * in a critical section.
+        */
+       InitXLogInsert();
+
        /*
         * Acquire CheckpointLock to ensure only one checkpoint happens at a time.
         * (This is just pro forma, since in the present system structure there is
index 34e44e4f235a7b5f30e4168c3e5366246fe0060a..f1bf728c3d2ddb45394d6ad5b96b70dc2c81ac4a 100644 (file)
@@ -891,5 +891,6 @@ InitXLogInsert(void)
         * Allocate a buffer to hold the header information for a WAL record.
         */
        if (hdr_scratch == NULL)
-               hdr_scratch = palloc0(HEADER_SCRATCH_SIZE);
+               hdr_scratch = MemoryContextAllocZero(xloginsert_cxt,
+                                                                                        HEADER_SCRATCH_SIZE);
 }