Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1296d5c

Browse files
committed
Fix a couple of error-handling bugs in the xlogreader patch.
XLogReadRecord should reset its state on every error, to make sure it re-reads the page on next call. It was inconsistent in that some errors did that, but some did not. In ReadRecord(), don't give up on an error if we're in standby mode. The loop was set up to retry, but the checks within the loop broke out of the loop on any error. Andres Freund, with some tweaking by me.
1 parent b14f81b commit 1296d5c

File tree

2 files changed

+28
-33
lines changed

2 files changed

+28
-33
lines changed

src/backend/access/transam/xlog.c

+21-10
Original file line numberDiff line numberDiff line change
@@ -3180,7 +3180,8 @@ RestoreBackupBlock(XLogRecPtr lsn, XLogRecord *record, int block_index,
31803180
* try to read a record just after the last one previously read.
31813181
*
31823182
* If no valid record is available, returns NULL, or fails if emode is PANIC.
3183-
* (emode must be either PANIC, LOG)
3183+
* (emode must be either PANIC, LOG). In standby mode, retries until a valid
3184+
* record is available.
31843185
*
31853186
* The record is copied into readRecordBuf, so that on successful return,
31863187
* the returned record pointer always points there.
@@ -3209,20 +3210,27 @@ ReadRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr, int emode,
32093210
EndRecPtr = xlogreader->EndRecPtr;
32103211
if (record == NULL)
32113212
{
3212-
/* not all failures fill errormsg; report those that do */
3213-
if (errormsg && errormsg[0] != '\0')
3214-
ereport(emode_for_corrupt_record(emode,
3215-
RecPtr ? RecPtr : EndRecPtr),
3216-
(errmsg_internal("%s", errormsg) /* already translated */));
3217-
32183213
lastSourceFailed = true;
32193214

32203215
if (readFile >= 0)
32213216
{
32223217
close(readFile);
32233218
readFile = -1;
32243219
}
3225-
break;
3220+
3221+
/*
3222+
* We only end up here without a message when XLogPageRead() failed
3223+
* - in that case we already logged something.
3224+
* In StandbyMode that only happens if we have been triggered, so
3225+
* we shouldn't loop anymore in that case.
3226+
*/
3227+
if (errormsg)
3228+
ereport(emode_for_corrupt_record(emode,
3229+
RecPtr ? RecPtr : EndRecPtr),
3230+
(errmsg_internal("%s", errormsg) /* already translated */));
3231+
3232+
/* Give up, or retry if we're in standby mode. */
3233+
continue;
32263234
}
32273235

32283236
/*
@@ -3234,6 +3242,8 @@ ReadRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr, int emode,
32343242
XLogSegNo segno;
32353243
int32 offset;
32363244

3245+
lastSourceFailed = true;
3246+
32373247
XLByteToSeg(xlogreader->latestPagePtr, segno);
32383248
offset = xlogreader->latestPagePtr % XLogSegSize;
32393249
XLogFileName(fname, xlogreader->readPageTLI, segno);
@@ -3243,9 +3253,10 @@ ReadRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr, int emode,
32433253
xlogreader->latestPageTLI,
32443254
fname,
32453255
offset)));
3246-
return false;
3256+
record = NULL;
3257+
continue;
32473258
}
3248-
} while (StandbyMode && record == NULL);
3259+
} while (StandbyMode && record == NULL && !CheckForStandbyTrigger());
32493260

32503261
return record;
32513262
}

src/backend/access/transam/xlogreader.c

+7-23
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,7 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
222222
readOff = ReadPageInternal(state, targetPagePtr, SizeOfXLogRecord);
223223

224224
if (readOff < 0)
225-
{
226-
if (state->errormsg_buf[0] != '\0')
227-
*errormsg = state->errormsg_buf;
228-
return NULL;
229-
}
225+
goto err;
230226

231227
/*
232228
* ReadPageInternal always returns at least the page header, so we can
@@ -246,17 +242,15 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
246242
{
247243
report_invalid_record(state, "invalid record offset at %X/%X",
248244
(uint32) (RecPtr >> 32), (uint32) RecPtr);
249-
*errormsg = state->errormsg_buf;
250-
return NULL;
245+
goto err;
251246
}
252247

253248
if ((((XLogPageHeader) state->readBuf)->xlp_info & XLP_FIRST_IS_CONTRECORD) &&
254249
targetRecOff == pageHeaderSize)
255250
{
256251
report_invalid_record(state, "contrecord is requested by %X/%X",
257252
(uint32) (RecPtr >> 32), (uint32) RecPtr);
258-
*errormsg = state->errormsg_buf;
259-
return NULL;
253+
goto err;
260254
}
261255

262256
/* ReadPageInternal has verified the page header */
@@ -270,11 +264,7 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
270264
targetPagePtr,
271265
Min(targetRecOff + SizeOfXLogRecord, XLOG_BLCKSZ));
272266
if (readOff < 0)
273-
{
274-
if (state->errormsg_buf[0] != '\0')
275-
*errormsg = state->errormsg_buf;
276-
return NULL;
277-
}
267+
goto err;
278268

279269
/*
280270
* Read the record length.
@@ -300,11 +290,7 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
300290
{
301291
if (!ValidXLogRecordHeader(state, RecPtr, state->ReadRecPtr, record,
302292
randAccess))
303-
{
304-
if (state->errormsg_buf[0] != '\0')
305-
*errormsg = state->errormsg_buf;
306-
return NULL;
307-
}
293+
goto err;
308294
gotheader = true;
309295
}
310296
else
@@ -314,8 +300,7 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
314300
{
315301
report_invalid_record(state, "invalid record length at %X/%X",
316302
(uint32) (RecPtr >> 32), (uint32) RecPtr);
317-
*errormsg = state->errormsg_buf;
318-
return NULL;
303+
goto err;
319304
}
320305
gotheader = false;
321306
}
@@ -330,8 +315,7 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
330315
report_invalid_record(state, "record length %u at %X/%X too long",
331316
total_len,
332317
(uint32) (RecPtr >> 32), (uint32) RecPtr);
333-
*errormsg = state->errormsg_buf;
334-
return NULL;
318+
goto err;
335319
}
336320

337321
len = XLOG_BLCKSZ - RecPtr % XLOG_BLCKSZ;

0 commit comments

Comments
 (0)