Fix error handling of XLogReaderAllocate in case of OOM
Similarly to previous fix 9b8d478, commit 2c03216 has switched XLogReaderAllocate() to use a set of palloc calls instead of malloc, causing any callers of this function to fail with an error instead of receiving a NULL pointer in case of out-of-memory error. Fix this by using palloc_extended with MCXT_ALLOC_NO_OOM that will safely return NULL in case of an OOM. Michael Paquier, slightly modified by me.
This commit is contained in:
parent
f85155e18c
commit
6e4bf4ecd3
@ -1062,8 +1062,11 @@ XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn)
|
|||||||
if (!debug_reader)
|
if (!debug_reader)
|
||||||
debug_reader = XLogReaderAllocate(NULL, NULL);
|
debug_reader = XLogReaderAllocate(NULL, NULL);
|
||||||
|
|
||||||
if (!debug_reader ||
|
if (!debug_reader)
|
||||||
!DecodeXLogRecord(debug_reader, (XLogRecord *) recordBuf.data,
|
{
|
||||||
|
appendStringInfo(&buf, "error decoding record: out of memory");
|
||||||
|
}
|
||||||
|
else if (!DecodeXLogRecord(debug_reader, (XLogRecord *) recordBuf.data,
|
||||||
&errormsg))
|
&errormsg))
|
||||||
{
|
{
|
||||||
appendStringInfo(&buf, "error decoding record: %s",
|
appendStringInfo(&buf, "error decoding record: %s",
|
||||||
|
@ -58,15 +58,18 @@ report_invalid_record(XLogReaderState *state, const char *fmt,...)
|
|||||||
/*
|
/*
|
||||||
* Allocate and initialize a new XLogReader.
|
* Allocate and initialize a new XLogReader.
|
||||||
*
|
*
|
||||||
* The returned XLogReader is palloc'd. (In FRONTEND code, that means that
|
* Returns NULL if the xlogreader couldn't be allocated.
|
||||||
* running out-of-memory causes an immediate exit(1).
|
|
||||||
*/
|
*/
|
||||||
XLogReaderState *
|
XLogReaderState *
|
||||||
XLogReaderAllocate(XLogPageReadCB pagereadfunc, void *private_data)
|
XLogReaderAllocate(XLogPageReadCB pagereadfunc, void *private_data)
|
||||||
{
|
{
|
||||||
XLogReaderState *state;
|
XLogReaderState *state;
|
||||||
|
|
||||||
state = (XLogReaderState *) palloc0(sizeof(XLogReaderState));
|
state = (XLogReaderState *)
|
||||||
|
palloc_extended(sizeof(XLogReaderState),
|
||||||
|
MCXT_ALLOC_NO_OOM | MCXT_ALLOC_ZERO);
|
||||||
|
if (!state)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
state->max_block_id = -1;
|
state->max_block_id = -1;
|
||||||
|
|
||||||
@ -74,17 +77,30 @@ XLogReaderAllocate(XLogPageReadCB pagereadfunc, void *private_data)
|
|||||||
* Permanently allocate readBuf. We do it this way, rather than just
|
* Permanently allocate readBuf. We do it this way, rather than just
|
||||||
* making a static array, for two reasons: (1) no need to waste the
|
* making a static array, for two reasons: (1) no need to waste the
|
||||||
* storage in most instantiations of the backend; (2) a static char array
|
* storage in most instantiations of the backend; (2) a static char array
|
||||||
* isn't guaranteed to have any particular alignment, whereas palloc()
|
* isn't guaranteed to have any particular alignment, whereas
|
||||||
* will provide MAXALIGN'd storage.
|
* palloc_extended() will provide MAXALIGN'd storage.
|
||||||
*/
|
*/
|
||||||
state->readBuf = (char *) palloc(XLOG_BLCKSZ);
|
state->readBuf = (char *) palloc_extended(XLOG_BLCKSZ,
|
||||||
|
MCXT_ALLOC_NO_OOM);
|
||||||
|
if (!state->readBuf)
|
||||||
|
{
|
||||||
|
pfree(state);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
state->read_page = pagereadfunc;
|
state->read_page = pagereadfunc;
|
||||||
/* system_identifier initialized to zeroes above */
|
/* system_identifier initialized to zeroes above */
|
||||||
state->private_data = private_data;
|
state->private_data = private_data;
|
||||||
/* ReadRecPtr and EndRecPtr initialized to zeroes above */
|
/* ReadRecPtr and EndRecPtr initialized to zeroes above */
|
||||||
/* readSegNo, readOff, readLen, readPageTLI initialized to zeroes above */
|
/* readSegNo, readOff, readLen, readPageTLI initialized to zeroes above */
|
||||||
state->errormsg_buf = palloc(MAX_ERRORMSG_LEN + 1);
|
state->errormsg_buf = palloc_extended(MAX_ERRORMSG_LEN + 1,
|
||||||
|
MCXT_ALLOC_NO_OOM);
|
||||||
|
if (!state->errormsg_buf)
|
||||||
|
{
|
||||||
|
pfree(state->readBuf);
|
||||||
|
pfree(state);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
state->errormsg_buf[0] = '\0';
|
state->errormsg_buf[0] = '\0';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -163,6 +163,11 @@ StartupDecodingContext(List *output_plugin_options,
|
|||||||
ctx->slot = slot;
|
ctx->slot = slot;
|
||||||
|
|
||||||
ctx->reader = XLogReaderAllocate(read_page, ctx);
|
ctx->reader = XLogReaderAllocate(read_page, ctx);
|
||||||
|
if (!ctx->reader)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||||
|
errmsg("out of memory")));
|
||||||
|
|
||||||
ctx->reader->private_data = ctx;
|
ctx->reader->private_data = ctx;
|
||||||
|
|
||||||
ctx->reorder = ReorderBufferAllocate();
|
ctx->reorder = ReorderBufferAllocate();
|
||||||
|
@ -70,6 +70,8 @@ extractPageMap(const char *datadir, XLogRecPtr startpoint, TimeLineID tli,
|
|||||||
private.datadir = datadir;
|
private.datadir = datadir;
|
||||||
private.tli = tli;
|
private.tli = tli;
|
||||||
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
|
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
|
||||||
|
if (xlogreader == NULL)
|
||||||
|
pg_fatal("out of memory");
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -121,6 +123,8 @@ readOneRecord(const char *datadir, XLogRecPtr ptr, TimeLineID tli)
|
|||||||
private.datadir = datadir;
|
private.datadir = datadir;
|
||||||
private.tli = tli;
|
private.tli = tli;
|
||||||
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
|
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
|
||||||
|
if (xlogreader == NULL)
|
||||||
|
pg_fatal("out of memory");
|
||||||
|
|
||||||
record = XLogReadRecord(xlogreader, ptr, &errormsg);
|
record = XLogReadRecord(xlogreader, ptr, &errormsg);
|
||||||
if (record == NULL)
|
if (record == NULL)
|
||||||
@ -171,6 +175,8 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, TimeLineID tli,
|
|||||||
private.datadir = datadir;
|
private.datadir = datadir;
|
||||||
private.tli = tli;
|
private.tli = tli;
|
||||||
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
|
xlogreader = XLogReaderAllocate(&SimpleXLogPageRead, &private);
|
||||||
|
if (xlogreader == NULL)
|
||||||
|
pg_fatal("out of memory");
|
||||||
|
|
||||||
searchptr = forkptr;
|
searchptr = forkptr;
|
||||||
for (;;)
|
for (;;)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user