Work around gcc 4.6.0 bug

This commit is contained in:
Tom Lane 2011-06-10 17:16:01 -04:00
parent cbf5959e96
commit 562fb683df
2 changed files with 117 additions and 1 deletions

View File

@ -0,0 +1,111 @@
Back-patch upstream patch to cope with a gcc 4.6.0 bug. This will be
in PG 9.0.5 and later, but we need it in Fedora *now* because the bug
breaks WAL replay, thus causing crash recovery failures as well as the
originally reported symptom of frequent reconnections during standby.
commit 45d792f70272ed57b932816562f31c2f79426c2a
Author: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri Jun 10 17:03:11 2011 -0400
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
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index bf8075d..6c18db4 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -3676,23 +3676,32 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, bool fetching_ckpt)
RecPtr = &tmpRecPtr;
/*
- * Align recptr to next page if no more records can fit on the current
- * page.
+ * RecPtr is pointing to end+1 of the previous WAL record. We must
+ * advance it if necessary to where the next record starts. First,
+ * align to next page if no more records can fit on the current page.
*/
if (XLOG_BLCKSZ - (RecPtr->xrecoff % XLOG_BLCKSZ) < SizeOfXLogRecord)
- {
- NextLogPage(tmpRecPtr);
- /* We will account for page header size below */
- }
+ NextLogPage(*RecPtr);
- if (tmpRecPtr.xrecoff >= XLogFileSize)
+ /* Check for crossing of xlog segment boundary */
+ if (RecPtr->xrecoff >= XLogFileSize)
{
- (tmpRecPtr.xlogid)++;
- tmpRecPtr.xrecoff = 0;
+ (RecPtr->xlogid)++;
+ RecPtr->xrecoff = 0;
}
+
+ /*
+ * If at page start, we must skip over the page header. But we can't
+ * do that until we've read in the page, since the header size is
+ * variable.
+ */
}
else
{
+ /*
+ * In this case, the passed-in record pointer should already be
+ * pointing to a valid record starting position.
+ */
if (!XRecOffIsValid(RecPtr->xrecoff))
ereport(PANIC,
(errmsg("invalid record offset at %X/%X",
@@ -3721,11 +3730,13 @@ retry:
if (targetRecOff == 0)
{
/*
- * Can only get here in the continuing-from-prev-page case, because
- * XRecOffIsValid eliminated the zero-page-offset case otherwise. Need
- * to skip over the new page's header.
+ * At page start, so skip over page header. The Assert checks that
+ * we're not scribbling on caller's record pointer; it's OK because we
+ * can only get here in the continuing-from-prev-record case, since
+ * XRecOffIsValid rejected the zero-page-offset case otherwise.
*/
- tmpRecPtr.xrecoff += pageHeaderSize;
+ Assert(RecPtr == &tmpRecPtr);
+ RecPtr->xrecoff += pageHeaderSize;
targetRecOff = pageHeaderSize;
}
else if (targetRecOff < pageHeaderSize)
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 3f0930f..367de37 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -154,13 +154,13 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
/* Align a record pointer to next page */
#define NextLogPage(recptr) \
do { \
- if (recptr.xrecoff % XLOG_BLCKSZ != 0) \
- recptr.xrecoff += \
- (XLOG_BLCKSZ - recptr.xrecoff % XLOG_BLCKSZ); \
- if (recptr.xrecoff >= XLogFileSize) \
+ if ((recptr).xrecoff % XLOG_BLCKSZ != 0) \
+ (recptr).xrecoff += \
+ (XLOG_BLCKSZ - (recptr).xrecoff % XLOG_BLCKSZ); \
+ if ((recptr).xrecoff >= XLogFileSize) \
{ \
- (recptr.xlogid)++; \
- recptr.xrecoff = 0; \
+ ((recptr).xlogid)++; \
+ (recptr).xrecoff = 0; \
} \
} while (0)

View File

@ -54,7 +54,7 @@ Summary: PostgreSQL client programs
Name: postgresql
%global majorversion 9.0
Version: 9.0.4
Release: 2%{?dist}
Release: 3%{?dist}
# The PostgreSQL license is very similar to other MIT licenses, but the OSI
# recognizes it as an independent license, so we do as well.
License: PostgreSQL
@ -85,6 +85,7 @@ Source15: postgresql-bashprofile
Patch1: rpm-pgsql.patch
Patch2: postgresql-logging.patch
Patch3: postgresql-perl-rpath.patch
Patch4: postgresql-gcc-workaround.patch
BuildRequires: perl(ExtUtils::MakeMaker) glibc-devel bison flex gawk
BuildRequires: perl(ExtUtils::Embed), perl-devel
@ -302,6 +303,7 @@ system, including regression tests and benchmarks.
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
# We used to run autoconf here, but there's no longer any real need to,
# since Postgres ships with a reasonably modern configure script.
@ -820,6 +822,9 @@ rm -rf $RPM_BUILD_ROOT
%endif
%changelog
* Fri Jun 10 2011 Tom Lane <tgl@redhat.com> 9.0.4-3
- Work around gcc 4.6.0 bug (temporary backport from next upstream release)
* Tue May 10 2011 Tom Lane <tgl@redhat.com> 9.0.4-2
- Add LSB init block to initscript, to ensure sane ordering at system boot
Resolves: #703215