Skip to content

Commit b863d8d

Browse files
committed
Add guard to prevent recursive memory context logging.
Previously, if memory context logging was triggered repeatedly and rapidly while a previous request was still being processed, it could result in recursive calls to ProcessLogMemoryContextInterrupt(). This could lead to infinite recursion and potentially crash the process. This commit adds a guard to prevent such recursion. If ProcessLogMemoryContextInterrupt() is already in progress and logging memory contexts, subsequent calls will exit immediately, avoiding unintended recursive calls. While this scenario is unlikely in practice, it's not impossible. This change adds a safety check to prevent such failures. Back-patch to v14, where memory context logging was introduced. Reported-by: Robert Haas <robertmhaas@gmail.com> Author: Fujii Masao <masao.fujii@gmail.com> Reviewed-by: Atsushi Torikoshi <torikoshia@oss.nttdata.com> Reviewed-by: Robert Haas <robertmhaas@gmail.com> Reviewed-by: Artem Gavrilov <artem.gavrilov@percona.com> Discussion: https://postgr.es/m/CA+TgmoZMrv32tbNRrFTvF9iWLnTGqbhYSLVcrHGuwZvCtph0NA@mail.gmail.com Backpatch-through: 14
1 parent 573e679 commit b863d8d

File tree

1 file changed

+40
-18
lines changed

1 file changed

+40
-18
lines changed

src/backend/utils/mmgr/mcxt.c

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ MemoryContext CurTransactionContext = NULL;
157157
/* This is a transient link to the active portal's memory context: */
158158
MemoryContext PortalContext = NULL;
159159

160+
/* Is memory context logging currently in progress? */
161+
static bool LogMemoryContextInProgress = false;
162+
160163
static void MemoryContextDeleteOnly(MemoryContext context);
161164
static void MemoryContextCallResetCallbacks(MemoryContext context);
162165
static void MemoryContextStatsInternal(MemoryContext context, int level,
@@ -1295,26 +1298,45 @@ ProcessLogMemoryContextInterrupt(void)
12951298
LogMemoryContextPending = false;
12961299

12971300
/*
1298-
* Use LOG_SERVER_ONLY to prevent this message from being sent to the
1299-
* connected client.
1301+
* Exit immediately if memory context logging is already in progress. This
1302+
* prevents recursive calls, which could occur if logging is requested
1303+
* repeatedly and rapidly, potentially leading to infinite recursion and a
1304+
* crash.
13001305
*/
1301-
ereport(LOG_SERVER_ONLY,
1302-
(errhidestmt(true),
1303-
errhidecontext(true),
1304-
errmsg("logging memory contexts of PID %d", MyProcPid)));
1306+
if (LogMemoryContextInProgress)
1307+
return;
1308+
LogMemoryContextInProgress = true;
13051309

1306-
/*
1307-
* When a backend process is consuming huge memory, logging all its memory
1308-
* contexts might overrun available disk space. To prevent this, we limit
1309-
* the depth of the hierarchy, as well as the number of child contexts to
1310-
* log per parent to 100.
1311-
*
1312-
* As with MemoryContextStats(), we suppose that practical cases where the
1313-
* dump gets long will typically be huge numbers of siblings under the
1314-
* same parent context; while the additional debugging value from seeing
1315-
* details about individual siblings beyond 100 will not be large.
1316-
*/
1317-
MemoryContextStatsDetail(TopMemoryContext, 100, 100, false);
1310+
PG_TRY();
1311+
{
1312+
/*
1313+
* Use LOG_SERVER_ONLY to prevent this message from being sent to the
1314+
* connected client.
1315+
*/
1316+
ereport(LOG_SERVER_ONLY,
1317+
(errhidestmt(true),
1318+
errhidecontext(true),
1319+
errmsg("logging memory contexts of PID %d", MyProcPid)));
1320+
1321+
/*
1322+
* When a backend process is consuming huge memory, logging all its
1323+
* memory contexts might overrun available disk space. To prevent
1324+
* this, we limit the depth of the hierarchy, as well as the number of
1325+
* child contexts to log per parent to 100.
1326+
*
1327+
* As with MemoryContextStats(), we suppose that practical cases where
1328+
* the dump gets long will typically be huge numbers of siblings under
1329+
* the same parent context; while the additional debugging value from
1330+
* seeing details about individual siblings beyond 100 will not be
1331+
* large.
1332+
*/
1333+
MemoryContextStatsDetail(TopMemoryContext, 100, 100, false);
1334+
}
1335+
PG_FINALLY();
1336+
{
1337+
LogMemoryContextInProgress = false;
1338+
}
1339+
PG_END_TRY();
13181340
}
13191341

13201342
void *

0 commit comments

Comments
 (0)