diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 7d4e24fa30..ef6311b075 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -202,14 +202,6 @@ AuxiliaryProcessMain(int argc, char *argv[]) MyStartTime = time(NULL); - /* - * Fire up essential subsystems: error and memory management - * - * If we are running under the postmaster, this is done already. - */ - if (!IsUnderPostmaster) - MemoryContextInit(); - /* Compute paths, if we didn't inherit them from postmaster */ if (my_exec_path[0] == '\0') { diff --git a/src/backend/main/main.c b/src/backend/main/main.c index 4ee8a153d9..98da177de9 100644 --- a/src/backend/main/main.c +++ b/src/backend/main/main.c @@ -39,6 +39,7 @@ #include "postmaster/postmaster.h" #include "tcop/tcopprot.h" #include "utils/help_config.h" +#include "utils/memutils.h" #include "utils/pg_locale.h" #include "utils/ps_status.h" @@ -85,6 +86,15 @@ main(int argc, char *argv[]) pgwin32_install_crashdump_handler(); #endif + /* + * Fire up essential subsystems: error and memory management + * + * Code after this point is allowed to use elog/ereport, though + * localization of messages may not work right away, and messages won't go + * anywhere but stderr until GUC settings get loaded. + */ + MemoryContextInit(); + /* * Set up locale information from environment. Note that LC_CTYPE and * LC_COLLATE will be overridden later from pg_control if we are in an diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index a7e40cc4a5..23f4ada7b9 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -560,11 +560,6 @@ PostmasterMain(int argc, char *argv[]) */ umask(S_IRWXG | S_IRWXO); - /* - * Fire up essential subsystems: memory management - */ - MemoryContextInit(); - /* * By default, palloc() requests in the postmaster will be allocated in * the PostmasterContext, which is space that can be recycled by backends. @@ -4468,7 +4463,6 @@ SubPostmasterMain(int argc, char *argv[]) whereToSendOutput = DestNone; /* Setup essential subsystems (to ensure elog() behaves sanely) */ - MemoryContextInit(); InitializeGUCOptions(); /* Read in the variables file */ diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index dcd8cdf3c1..b7612b9b5f 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -3548,14 +3548,6 @@ PostgresMain(int argc, char *argv[], MyStartTime = time(NULL); } - /* - * Fire up essential subsystems: error and memory management - * - * If we are running under the postmaster, this is done already. - */ - if (!IsUnderPostmaster) - MemoryContextInit(); - SetProcessingMode(InitProcessing); /* Compute paths, if we didn't inherit them from postmaster */ diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index 3de162b9d5..8705586d56 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -310,6 +310,18 @@ errstart(int elevel, const char *filename, int lineno, if (elevel < ERROR && !output_to_server && !output_to_client) return false; + /* + * We need to do some actual work. Make sure that memory context + * initialization has finished, else we can't do anything useful. + */ + if (ErrorContext == NULL) + { + /* Ooops, hard crash time; very little we can do safely here */ + write_stderr("error occurred at %s:%d before error message processing is available\n", + filename ? filename : "(unknown file)", lineno); + exit(2); + } + /* * Okay, crank up a stack entry to store the info in. */ @@ -1238,6 +1250,15 @@ elog_start(const char *filename, int lineno, const char *funcname) { ErrorData *edata; + /* Make sure that memory context initialization has finished */ + if (ErrorContext == NULL) + { + /* Ooops, hard crash time; very little we can do safely here */ + write_stderr("error occurred at %s:%d before error message processing is available\n", + filename ? filename : "(unknown file)", lineno); + exit(2); + } + if (++errordata_stack_depth >= ERRORDATA_STACK_SIZE) { /* diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c index b60ca90d0a..7b089f77df 100644 --- a/src/backend/utils/mmgr/mcxt.c +++ b/src/backend/utils/mmgr/mcxt.c @@ -72,7 +72,8 @@ static void MemoryContextStatsInternal(MemoryContext context, int level); * In normal multi-backend operation, this is called once during * postmaster startup, and not at all by individual backend startup * (since the backends inherit an already-initialized context subsystem - * by virtue of being forked off the postmaster). + * by virtue of being forked off the postmaster). But in an EXEC_BACKEND + * build, each process must do this for itself. * * In a standalone backend this must be called during backend startup. */ @@ -106,6 +107,9 @@ MemoryContextInit(void) * where retained memory in a context is *essential* --- we want to be * sure ErrorContext still has some memory even if we've run out * elsewhere! + * + * This should be the last step in this function, as elog.c assumes memory + * management works once ErrorContext is non-null. */ ErrorContext = AllocSetContextCreate(TopMemoryContext, "ErrorContext",