Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit910bac5

Browse files
committed
Fix possible crashes due to using elog/ereport too early in startup.
Per reports from Andres Freund and Luke Campbell, a server failure duringset_pglocale_pgservice results in a segfault rather than a useful errormessage, because the infrastructure needed to use ereport hasn't beeninitialized; specifically, MemoryContextInit hasn't been called.One known cause of this is starting the server in a directory itdoesn't have permission to read.We could try to prevent set_pglocale_pgservice from using anything thatdepends on palloc or elog, but that would be messy, and the odds of futurebreakage seem high. Moreover there are other things being called in main.cthat look likely to use palloc or elog too --- perhaps those thingsshouldn't be there, but they are there today. The best solution seems tobe to move the call of MemoryContextInit to very early in the backend'sreal main() function. I've verified that an elog or ereport occurringimmediately after that is now capable of sending something useful tostderr.I also added code to elog.c to print something intelligible rather thanjust crashing if MemoryContextInit hasn't created the ErrorContext.This could happen if MemoryContextInit itself fails (due to mallocfailure), and provides some future-proofing against someone trying tosneak in new code even earlier in server startup.Back-patch to all supported branches. Since we've only heard reports ofthis type of failure recently, it may be that some recent change has madeit more likely to see a crash of this kind; but it sure looks like it'sbroken all the way back.
1 parentd84c584 commit910bac5

File tree

6 files changed

+36
-23
lines changed

6 files changed

+36
-23
lines changed

‎src/backend/bootstrap/bootstrap.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,6 @@ AuxiliaryProcessMain(int argc, char *argv[])
202202

203203
MyStartTime=time(NULL);
204204

205-
/*
206-
* Fire up essential subsystems: error and memory management
207-
*
208-
* If we are running under the postmaster, this is done already.
209-
*/
210-
if (!IsUnderPostmaster)
211-
MemoryContextInit();
212-
213205
/* Compute paths, if we didn't inherit them from postmaster */
214206
if (my_exec_path[0]=='\0')
215207
{

‎src/backend/main/main.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include"postmaster/postmaster.h"
4040
#include"tcop/tcopprot.h"
4141
#include"utils/help_config.h"
42+
#include"utils/memutils.h"
4243
#include"utils/pg_locale.h"
4344
#include"utils/ps_status.h"
4445

@@ -85,6 +86,15 @@ main(int argc, char *argv[])
8586
pgwin32_install_crashdump_handler();
8687
#endif
8788

89+
/*
90+
* Fire up essential subsystems: error and memory management
91+
*
92+
* Code after this point is allowed to use elog/ereport, though
93+
* localization of messages may not work right away, and messages won't go
94+
* anywhere but stderr until GUC settings get loaded.
95+
*/
96+
MemoryContextInit();
97+
8898
/*
8999
* Set up locale information from environment.Note that LC_CTYPE and
90100
* LC_COLLATE will be overridden later from pg_control if we are in an

‎src/backend/postmaster/postmaster.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -560,11 +560,6 @@ PostmasterMain(int argc, char *argv[])
560560
*/
561561
umask(S_IRWXG |S_IRWXO);
562562

563-
/*
564-
* Fire up essential subsystems: memory management
565-
*/
566-
MemoryContextInit();
567-
568563
/*
569564
* By default, palloc() requests in the postmaster will be allocated in
570565
* the PostmasterContext, which is space that can be recycled by backends.
@@ -4468,7 +4463,6 @@ SubPostmasterMain(int argc, char *argv[])
44684463
whereToSendOutput=DestNone;
44694464

44704465
/* Setup essential subsystems (to ensure elog() behaves sanely) */
4471-
MemoryContextInit();
44724466
InitializeGUCOptions();
44734467

44744468
/* Read in the variables file */

‎src/backend/tcop/postgres.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3548,14 +3548,6 @@ PostgresMain(int argc, char *argv[],
35483548
MyStartTime=time(NULL);
35493549
}
35503550

3551-
/*
3552-
* Fire up essential subsystems: error and memory management
3553-
*
3554-
* If we are running under the postmaster, this is done already.
3555-
*/
3556-
if (!IsUnderPostmaster)
3557-
MemoryContextInit();
3558-
35593551
SetProcessingMode(InitProcessing);
35603552

35613553
/* Compute paths, if we didn't inherit them from postmaster */

‎src/backend/utils/error/elog.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,18 @@ errstart(int elevel, const char *filename, int lineno,
310310
if (elevel<ERROR&& !output_to_server&& !output_to_client)
311311
return false;
312312

313+
/*
314+
* We need to do some actual work. Make sure that memory context
315+
* initialization has finished, else we can't do anything useful.
316+
*/
317+
if (ErrorContext==NULL)
318+
{
319+
/* Ooops, hard crash time; very little we can do safely here */
320+
write_stderr("error occurred at %s:%d before error message processing is available\n",
321+
filename ?filename :"(unknown file)",lineno);
322+
exit(2);
323+
}
324+
313325
/*
314326
* Okay, crank up a stack entry to store the info in.
315327
*/
@@ -1238,6 +1250,15 @@ elog_start(const char *filename, int lineno, const char *funcname)
12381250
{
12391251
ErrorData*edata;
12401252

1253+
/* Make sure that memory context initialization has finished */
1254+
if (ErrorContext==NULL)
1255+
{
1256+
/* Ooops, hard crash time; very little we can do safely here */
1257+
write_stderr("error occurred at %s:%d before error message processing is available\n",
1258+
filename ?filename :"(unknown file)",lineno);
1259+
exit(2);
1260+
}
1261+
12411262
if (++errordata_stack_depth >=ERRORDATA_STACK_SIZE)
12421263
{
12431264
/*

‎src/backend/utils/mmgr/mcxt.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ static void MemoryContextStatsInternal(MemoryContext context, int level);
7272
* In normal multi-backend operation, this is called once during
7373
* postmaster startup, and not at all by individual backend startup
7474
* (since the backends inherit an already-initialized context subsystem
75-
* by virtue of being forked off the postmaster).
75+
* by virtue of being forked off the postmaster). But in an EXEC_BACKEND
76+
* build, each process must do this for itself.
7677
*
7778
* In a standalone backend this must be called during backend startup.
7879
*/
@@ -106,6 +107,9 @@ MemoryContextInit(void)
106107
* where retained memory in a context is *essential* --- we want to be
107108
* sure ErrorContext still has some memory even if we've run out
108109
* elsewhere!
110+
*
111+
* This should be the last step in this function, as elog.c assumes memory
112+
* management works once ErrorContext is non-null.
109113
*/
110114
ErrorContext=AllocSetContextCreate(TopMemoryContext,
111115
"ErrorContext",

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp