Skip to content

Commit 45d792f

Browse files
committed
Work around gcc 4.6.0 bug that breaks WAL replay.
ReadRecord's habit of using both direct references to tmpRecPtr and references to *RecPtr (which is pointing at tmpRecPtr) triggers an optimization bug in gcc 4.6.0, which apparently has forgotten about aliasing rules. Avoid the compiler bug, and make the code more readable to boot, by getting rid of the direct references. Improve the comments while at it. Back-patch to all supported versions, in case they get built with 4.6.0. Tom Lane, with some cosmetic suggestions from Alex Hunsaker
1 parent cdd0888 commit 45d792f

File tree

2 files changed

+30
-19
lines changed

2 files changed

+30
-19
lines changed

src/backend/access/transam/xlog.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3676,23 +3676,32 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
36763676
RecPtr = &tmpRecPtr;
36773677

36783678
/*
3679-
* Align recptr to next page if no more records can fit on the current
3680-
* page.
3679+
* RecPtr is pointing to end+1 of the previous WAL record. We must
3680+
* advance it if necessary to where the next record starts. First,
3681+
* align to next page if no more records can fit on the current page.
36813682
*/
36823683
if (XLOG_BLCKSZ - (RecPtr->xrecoff % XLOG_BLCKSZ) < SizeOfXLogRecord)
3683-
{
3684-
NextLogPage(tmpRecPtr);
3685-
/* We will account for page header size below */
3686-
}
3684+
NextLogPage(*RecPtr);
36873685

3688-
if (tmpRecPtr.xrecoff >= XLogFileSize)
3686+
/* Check for crossing of xlog segment boundary */
3687+
if (RecPtr->xrecoff >= XLogFileSize)
36893688
{
3690-
(tmpRecPtr.xlogid)++;
3691-
tmpRecPtr.xrecoff = 0;
3689+
(RecPtr->xlogid)++;
3690+
RecPtr->xrecoff = 0;
36923691
}
3692+
3693+
/*
3694+
* If at page start, we must skip over the page header. But we can't
3695+
* do that until we've read in the page, since the header size is
3696+
* variable.
3697+
*/
36933698
}
36943699
else
36953700
{
3701+
/*
3702+
* In this case, the passed-in record pointer should already be
3703+
* pointing to a valid record starting position.
3704+
*/
36963705
if (!XRecOffIsValid(RecPtr->xrecoff))
36973706
ereport(PANIC,
36983707
(errmsg("invalid record offset at %X/%X",
@@ -3721,11 +3730,13 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
37213730
if (targetRecOff == 0)
37223731
{
37233732
/*
3724-
* Can only get here in the continuing-from-prev-page case, because
3725-
* XRecOffIsValid eliminated the zero-page-offset case otherwise. Need
3726-
* to skip over the new page's header.
3733+
* At page start, so skip over page header. The Assert checks that
3734+
* we're not scribbling on caller's record pointer; it's OK because we
3735+
* can only get here in the continuing-from-prev-record case, since
3736+
* XRecOffIsValid rejected the zero-page-offset case otherwise.
37273737
*/
3728-
tmpRecPtr.xrecoff += pageHeaderSize;
3738+
Assert(RecPtr == &tmpRecPtr);
3739+
RecPtr->xrecoff += pageHeaderSize;
37293740
targetRecOff = pageHeaderSize;
37303741
}
37313742
else if (targetRecOff < pageHeaderSize)

src/include/access/xlog_internal.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,13 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
154154
/* Align a record pointer to next page */
155155
#define NextLogPage(recptr) \
156156
do { \
157-
if (recptr.xrecoff % XLOG_BLCKSZ != 0) \
158-
recptr.xrecoff += \
159-
(XLOG_BLCKSZ - recptr.xrecoff % XLOG_BLCKSZ); \
160-
if (recptr.xrecoff >= XLogFileSize) \
157+
if ((recptr).xrecoff % XLOG_BLCKSZ != 0) \
158+
(recptr).xrecoff += \
159+
(XLOG_BLCKSZ - (recptr).xrecoff % XLOG_BLCKSZ); \
160+
if ((recptr).xrecoff >= XLogFileSize) \
161161
{ \
162-
(recptr.xlogid)++; \
163-
recptr.xrecoff = 0; \
162+
((recptr).xlogid)++; \
163+
(recptr).xrecoff = 0; \
164164
} \
165165
} while (0)
166166

0 commit comments

Comments
 (0)