Skip to content

Commit 0fc2f53

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 460d970 commit 0fc2f53

File tree

1 file changed

+40
-17
lines changed

1 file changed

+40
-17
lines changed

src/backend/utils/mmgr/mcxt.c

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ MemoryContext CurTransactionContext = NULL;
5656
/* This is a transient link to the active portal's memory context: */
5757
MemoryContext PortalContext = NULL;
5858

59+
/* Is memory context logging currently in progress? */
60+
static bool LogMemoryContextInProgress = false;
61+
5962
static void MemoryContextCallResetCallbacks(MemoryContext context);
6063
static void MemoryContextStatsInternal(MemoryContext context, int level,
6164
bool print, int max_children,
@@ -1043,25 +1046,45 @@ ProcessLogMemoryContextInterrupt(void)
10431046
LogMemoryContextPending = false;
10441047

10451048
/*
1046-
* Use LOG_SERVER_ONLY to prevent this message from being sent to the
1047-
* connected client.
1049+
* Exit immediately if memory context logging is already in progress. This
1050+
* prevents recursive calls, which could occur if logging is requested
1051+
* repeatedly and rapidly, potentially leading to infinite recursion and a
1052+
* crash.
10481053
*/
1049-
ereport(LOG_SERVER_ONLY,
1050-
(errhidestmt(true),
1051-
errhidecontext(true),
1052-
errmsg("logging memory contexts of PID %d", MyProcPid)));
1054+
if (LogMemoryContextInProgress)
1055+
return;
1056+
LogMemoryContextInProgress = true;
10531057

1054-
/*
1055-
* When a backend process is consuming huge memory, logging all its memory
1056-
* contexts might overrun available disk space. To prevent this, we limit
1057-
* the number of child contexts to log per parent to 100.
1058-
*
1059-
* As with MemoryContextStats(), we suppose that practical cases where the
1060-
* dump gets long will typically be huge numbers of siblings under the
1061-
* same parent context; while the additional debugging value from seeing
1062-
* details about individual siblings beyond 100 will not be large.
1063-
*/
1064-
MemoryContextStatsDetail(TopMemoryContext, 100, false);
1058+
PG_TRY();
1059+
{
1060+
/*
1061+
* Use LOG_SERVER_ONLY to prevent this message from being sent to the
1062+
* connected client.
1063+
*/
1064+
ereport(LOG_SERVER_ONLY,
1065+
(errhidestmt(true),
1066+
errhidecontext(true),
1067+
errmsg("logging memory contexts of PID %d", MyProcPid)));
1068+
1069+
/*
1070+
* When a backend process is consuming huge memory, logging all its
1071+
* memory contexts might overrun available disk space. To prevent
1072+
* this, we limit the number of child contexts to log per parent to
1073+
* 100.
1074+
*
1075+
* As with MemoryContextStats(), we suppose that practical cases where
1076+
* the dump gets long will typically be huge numbers of siblings under
1077+
* the same parent context; while the additional debugging value from
1078+
* seeing details about individual siblings beyond 100 will not be
1079+
* large.
1080+
*/
1081+
MemoryContextStatsDetail(TopMemoryContext, 100, false);
1082+
}
1083+
PG_FINALLY();
1084+
{
1085+
LogMemoryContextInProgress = false;
1086+
}
1087+
PG_END_TRY();
10651088
}
10661089

10671090
void *

0 commit comments

Comments
 (0)