Commit 6e4bf4ec authored by Fujii Masao's avatar Fujii Masao

Fix error handling of XLogReaderAllocate in case of OOM

Similarly to previous fix 9b8d4782, commit 2c03216d 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.
parent f85155e1
...@@ -1062,8 +1062,11 @@ XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn) ...@@ -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,...) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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 (;;)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment