Hi, I've previously complained ([1]) that process initialization has gotten very complicated. I hit this once more last week when trying to commit one of the shared memory stats pieces...
I think there's quite a few different issues around this - here I'm just trying to tackle a few of the most glaring (to me): - AuxiliaryProcessMain() is used for two independent tasks: Start bootstrap / checker mode and starting auxiliary processes. In HEAD there's maybe 5 lines out 250 that are actually common to both uses. A related oddity is that we reserve shared memory resources for bootstrap & checker aux processes, despite those never existing. This is addressed in patches 1-7 - The order of invocation of InitProcess()/InitAuxiliaryProcess() and BaseInit() depends on EXEC_BACKEND. Due to that there often is no single place initialization code can be put if it needs any locks. This is addressed in patches 8-9 - PostgresMain() has code for single user and multi user interleaved, making it unnecessarily hard to understand what's going on. This is addressed in patches 10 This isn't a patch series ready to commit, there's a bunch of polishing that needs to be done if there's agreement. Questions I have: - What exactly to do with checker mode: Keep it as part of bootstrap, separate it out completely? What commandline flags? - I used a separate argv entry to pass the aux proc type - do we rather want to go for the approach that e.g. bgworker went for? Adding code for string splitting seems a bit unnecessary to me. - PostgresMainSingle() should probably not be in postgres.c. We could put it into postinit.c or ..? - My first attempt at PostgresMainSingle() separated the single/multi user cases a bit more than the code right now, by having a PostgresMainCommon() which was called by PostgresMainSingle(), PostgresMain(). *Common only started with the MessageContext allocation, which did have the advantage of splitting out a few of the remaining conditional actions in PostgresMain() (PostmasterContext, welcome banner, Log_disconnections). But lead to a bit more duplication. I don't really have an opinion on what's better. - I had to move the PgStartTime computation to a bit earlier for single user mode. That seems to make sense to me anyway, given that postmaster does so fairly early too. Any reason that'd be a bad idea? Arguably it should even be a tad earlier to be symmetric. There's one further issue that I think is big enough to be worth tackling in the near future: Too many things depend on BackendIds. Aux processes need procsignal and backend status reporting, which use BackendId for indexing. But they don't use sinval, so they don't have a BackendId - so we have hacks to work around that in a few places. If we instead make those places use pgprocno for indexing the whole issue vanishes. In fact, I think there's a good argument to be made that we should entirely remove the concept of BackendIds and just use pgprocnos. We have a fair number of places like SignalVirtualTransaction() that need to search the procarray just to find the proc to signal based on the BackendId. If we used pgprocno instead, that'd not be needed. But perhaps that's a separate thread. Greetings, Andres Freund [1] https://postgr.es/m/20210402002240.56cuz3uo3alnqwae%40alap3.anarazel.de
>From 9ad9ca5aa6684ab15000913fd101e329b1e2a74d Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Fri, 30 Jul 2021 18:53:52 -0700 Subject: [PATCH v1 01/10] process startup: Rename postmaster's --forkboot to --forkaux. It is confusing that aux processes are started with --forkboot, given that bootstrap mode cannot run below postmaster. Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- src/backend/postmaster/postmaster.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 122c2b05bdb..df4b115c1e6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -4930,7 +4930,7 @@ SubPostmasterMain(int argc, char *argv[]) if (strcmp(argv[1], "--forkbackend") == 0 || strcmp(argv[1], "--forkavlauncher") == 0 || strcmp(argv[1], "--forkavworker") == 0 || - strcmp(argv[1], "--forkboot") == 0 || + strcmp(argv[1], "--forkaux") == 0 || strncmp(argv[1], "--forkbgworker=", 15) == 0) PGSharedMemoryReAttach(); else @@ -5018,7 +5018,7 @@ SubPostmasterMain(int argc, char *argv[]) /* And run the backend */ BackendRun(&port); /* does not return */ } - if (strcmp(argv[1], "--forkboot") == 0) + if (strcmp(argv[1], "--forkaux") == 0) { /* Restore basic shared memory pointers */ InitShmemAccess(UsedShmemSegAddr); @@ -5427,7 +5427,7 @@ StartChildProcess(AuxProcType type) av[ac++] = "postgres"; #ifdef EXEC_BACKEND - av[ac++] = "--forkboot"; + av[ac++] = "--forkaux"; av[ac++] = NULL; /* filled in by postmaster_forkexec */ #endif -- 2.32.0.rc2
>From 01d260c78f0c17e05f9e981b0184f826714b33bc Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Fri, 30 Jul 2021 20:04:32 -0700 Subject: [PATCH v1 02/10] process startup: Separate out BootstrapModeMain from AuxiliaryProcessMain. There practically was no shared code between the two, once all the ifs are removed. And it was quite confusing that aux processes weren't actually started by the call to AuxiliaryProcessMain() in main(). There's more to do, AuxiliaryProcessMain() should move out of bootstrap.c, and BootstrapModeMain() shouldn't use/be part of AuxProcType. Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- src/include/bootstrap/bootstrap.h | 4 +- src/backend/bootstrap/bootstrap.c | 366 ++++++++++++++-------------- src/backend/main/main.c | 2 +- src/backend/postmaster/postmaster.c | 43 ++-- 4 files changed, 206 insertions(+), 209 deletions(-) diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h index 8290d4c6c49..0f8762afaf8 100644 --- a/src/include/bootstrap/bootstrap.h +++ b/src/include/bootstrap/bootstrap.h @@ -15,6 +15,7 @@ #define BOOTSTRAP_H #include "nodes/execnodes.h" +#include "miscadmin.h" /* @@ -32,7 +33,8 @@ extern Form_pg_attribute attrtypes[MAXATTR]; extern int numattr; -extern void AuxiliaryProcessMain(int argc, char *argv[]) pg_attribute_noreturn(); +extern void BootstrapModeMain(int argc, char *argv[]) pg_attribute_noreturn(); +extern void AuxiliaryProcessMain(AuxProcType auxtype) pg_attribute_noreturn(); extern void closerel(char *name); extern void boot_openrel(char *name); diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 67cd5ac6e9a..d4f341937dc 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -55,7 +55,6 @@ uint32 bootstrap_data_checksum_version = 0; /* No checksum */ static void CheckerModeMain(void); -static void BootstrapModeMain(void); static void bootstrap_signals(void); static void ShutdownAuxiliaryProcess(int code, Datum arg); static Form_pg_attribute AllocateAttribute(void); @@ -194,33 +193,171 @@ static IndexList *ILHead = NULL; * This code is here just because of historical reasons. */ void -AuxiliaryProcessMain(int argc, char *argv[]) +AuxiliaryProcessMain(AuxProcType auxtype) { + Assert(IsUnderPostmaster); + + MyAuxProcType = auxtype; + + switch (MyAuxProcType) + { + case StartupProcess: + MyBackendType = B_STARTUP; + break; + case ArchiverProcess: + MyBackendType = B_ARCHIVER; + break; + case BgWriterProcess: + MyBackendType = B_BG_WRITER; + break; + case CheckpointerProcess: + MyBackendType = B_CHECKPOINTER; + break; + case WalWriterProcess: + MyBackendType = B_WAL_WRITER; + break; + case WalReceiverProcess: + MyBackendType = B_WAL_RECEIVER; + break; + default: + elog(ERROR, "something has gone wrong"); + MyBackendType = B_INVALID; + } + + init_ps_display(NULL); + + SetProcessingMode(BootstrapProcessing); + IgnoreSystemIndexes = true; + + BaseInit(); + + /* + * As an auxiliary process, we aren't going to do the full InitPostgres + * pushups, but there are a couple of things that need to get lit up even + * in an auxiliary process. + */ + { + /* + * Create a PGPROC so we can use LWLocks. In the EXEC_BACKEND case, + * this was already done by SubPostmasterMain(). + */ +#ifndef EXEC_BACKEND + InitAuxiliaryProcess(); +#endif + + /* + * Assign the ProcSignalSlot for an auxiliary process. Since it + * doesn't have a BackendId, the slot is statically allocated based on + * the auxiliary process type (MyAuxProcType). Backends use slots + * indexed in the range from 1 to MaxBackends (inclusive), so we use + * MaxBackends + AuxProcType + 1 as the index of the slot for an + * auxiliary process. + * + * This will need rethinking if we ever want more than one of a + * particular auxiliary process type. + */ + ProcSignalInit(MaxBackends + MyAuxProcType + 1); + + /* finish setting up bufmgr.c */ + InitBufferPoolBackend(); + + /* + * Auxiliary processes don't run transactions, but they may need a + * resource owner anyway to manage buffer pins acquired outside + * transactions (and, perhaps, other things in future). + */ + CreateAuxProcessResourceOwner(); + + /* Initialize statistics reporting */ + pgstat_initialize(); + + /* Initialize backend status information */ + pgstat_beinit(); + pgstat_bestart(); + + /* register a before-shutdown callback for LWLock cleanup */ + before_shmem_exit(ShutdownAuxiliaryProcess, 0); + } + + SetProcessingMode(NormalProcessing); + + switch (MyAuxProcType) + { + case CheckerProcess: + case BootstrapProcess: + pg_unreachable(); + break; + + case StartupProcess: + StartupProcessMain(); + proc_exit(1); + + case ArchiverProcess: + PgArchiverMain(); + proc_exit(1); + + case BgWriterProcess: + BackgroundWriterMain(); + proc_exit(1); + + case CheckpointerProcess: + CheckpointerMain(); + proc_exit(1); + + case WalWriterProcess: + InitXLOGAccess(); + WalWriterMain(); + proc_exit(1); + + case WalReceiverProcess: + WalReceiverMain(); + proc_exit(1); + + default: + elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType); + proc_exit(1); + } +} + +/* + * In shared memory checker mode, all we really want to do is create shared + * memory and semaphores (just to prove we can do it with the current GUC + * settings). Since, in fact, that was already done by BaseInit(), + * we have nothing more to do here. + */ +static void +CheckerModeMain(void) +{ + proc_exit(0); +} + +/* + * The main entry point for running the backend in bootstrap mode + * + * The bootstrap mode is used to initialize the template database. + * The bootstrap backend doesn't speak SQL, but instead expects + * commands in a special bootstrap language. + */ +void +BootstrapModeMain(int argc, char *argv[]) +{ + int i; char *progname = argv[0]; int flag; char *userDoption = NULL; - /* - * Initialize process environment (already done if under postmaster, but - * not if standalone). - */ - if (!IsUnderPostmaster) - InitStandaloneProcess(argv[0]); + Assert(!IsUnderPostmaster); - /* - * process command arguments - */ + InitStandaloneProcess(argv[0]); /* Set defaults, to be overridden by explicit options below */ - if (!IsUnderPostmaster) - InitializeGUCOptions(); + InitializeGUCOptions(); - /* Ignore the initial --boot argument, if present */ - if (argc > 1 && strcmp(argv[1], "--boot") == 0) - { - argv++; - argc--; - } + /* an initial --boot should be present */ + Assert(argc == 1 + || strcmp(argv[1], "--boot") != 0); + argv++; + argc--; /* If no -x argument, we are a CheckerProcess */ MyAuxProcType = CheckerProcess; @@ -259,6 +396,13 @@ AuxiliaryProcessMain(int argc, char *argv[]) break; case 'x': MyAuxProcType = atoi(optarg); + if (MyAuxProcType != CheckerProcess && + MyAuxProcType != BootstrapProcess) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("-x %s is invalid", optarg))); + } break; case 'X': { @@ -313,190 +457,36 @@ AuxiliaryProcessMain(int argc, char *argv[]) proc_exit(1); } - switch (MyAuxProcType) - { - case StartupProcess: - MyBackendType = B_STARTUP; - break; - case ArchiverProcess: - MyBackendType = B_ARCHIVER; - break; - case BgWriterProcess: - MyBackendType = B_BG_WRITER; - break; - case CheckpointerProcess: - MyBackendType = B_CHECKPOINTER; - break; - case WalWriterProcess: - MyBackendType = B_WAL_WRITER; - break; - case WalReceiverProcess: - MyBackendType = B_WAL_RECEIVER; - break; - default: - MyBackendType = B_INVALID; - } - if (IsUnderPostmaster) - init_ps_display(NULL); - - /* Acquire configuration parameters, unless inherited from postmaster */ - if (!IsUnderPostmaster) - { - if (!SelectConfigFiles(userDoption, progname)) - proc_exit(1); - } + /* Acquire configuration parameters */ + if (!SelectConfigFiles(userDoption, progname)) + proc_exit(1); /* * Validate we have been given a reasonable-looking DataDir and change - * into it (if under postmaster, should be done already). + * into it */ - if (!IsUnderPostmaster) - { - checkDataDir(); - ChangeToDataDir(); - } + checkDataDir(); + ChangeToDataDir(); - /* If standalone, create lockfile for data directory */ - if (!IsUnderPostmaster) - CreateDataDirLockFile(false); + CreateDataDirLockFile(false); SetProcessingMode(BootstrapProcessing); IgnoreSystemIndexes = true; - /* Initialize MaxBackends (if under postmaster, was done already) */ - if (!IsUnderPostmaster) - InitializeMaxBackends(); + InitializeMaxBackends(); BaseInit(); - /* - * When we are an auxiliary process, we aren't going to do the full - * InitPostgres pushups, but there are a couple of things that need to get - * lit up even in an auxiliary process. - */ - if (IsUnderPostmaster) + /* FIXME: Move out. New top-level mode? */ + if (MyAuxProcType == CheckerProcess) { - /* - * Create a PGPROC so we can use LWLocks. In the EXEC_BACKEND case, - * this was already done by SubPostmasterMain(). - */ -#ifndef EXEC_BACKEND - InitAuxiliaryProcess(); -#endif - - /* - * Assign the ProcSignalSlot for an auxiliary process. Since it - * doesn't have a BackendId, the slot is statically allocated based on - * the auxiliary process type (MyAuxProcType). Backends use slots - * indexed in the range from 1 to MaxBackends (inclusive), so we use - * MaxBackends + AuxProcType + 1 as the index of the slot for an - * auxiliary process. - * - * This will need rethinking if we ever want more than one of a - * particular auxiliary process type. - */ - ProcSignalInit(MaxBackends + MyAuxProcType + 1); - - /* finish setting up bufmgr.c */ - InitBufferPoolBackend(); - - /* - * Auxiliary processes don't run transactions, but they may need a - * resource owner anyway to manage buffer pins acquired outside - * transactions (and, perhaps, other things in future). - */ - CreateAuxProcessResourceOwner(); - - /* Initialize statistics reporting */ - pgstat_initialize(); - - /* Initialize backend status information */ - pgstat_beinit(); - pgstat_bestart(); - - /* register a before-shutdown callback for LWLock cleanup */ - before_shmem_exit(ShutdownAuxiliaryProcess, 0); + SetProcessingMode(NormalProcessing); + CheckerModeMain(); + abort(); } - SetProcessingMode(NormalProcessing); - - switch (MyAuxProcType) - { - case CheckerProcess: - /* don't set signals, they're useless here */ - CheckerModeMain(); - proc_exit(1); /* should never return */ - - case BootstrapProcess: - - /* - * There was a brief instant during which mode was Normal; this is - * okay. We need to be in bootstrap mode during BootStrapXLOG for - * the sake of multixact initialization. - */ - SetProcessingMode(BootstrapProcessing); - bootstrap_signals(); - BootStrapXLOG(); - BootstrapModeMain(); - proc_exit(1); /* should never return */ - - case StartupProcess: - StartupProcessMain(); - proc_exit(1); - - case ArchiverProcess: - PgArchiverMain(); - proc_exit(1); - - case BgWriterProcess: - BackgroundWriterMain(); - proc_exit(1); - - case CheckpointerProcess: - CheckpointerMain(); - proc_exit(1); - - case WalWriterProcess: - InitXLOGAccess(); - WalWriterMain(); - proc_exit(1); - - case WalReceiverProcess: - WalReceiverMain(); - proc_exit(1); - - default: - elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType); - proc_exit(1); - } -} - -/* - * In shared memory checker mode, all we really want to do is create shared - * memory and semaphores (just to prove we can do it with the current GUC - * settings). Since, in fact, that was already done by BaseInit(), - * we have nothing more to do here. - */ -static void -CheckerModeMain(void) -{ - proc_exit(0); -} - -/* - * The main entry point for running the backend in bootstrap mode - * - * The bootstrap mode is used to initialize the template database. - * The bootstrap backend doesn't speak SQL, but instead expects - * commands in a special bootstrap language. - */ -static void -BootstrapModeMain(void) -{ - int i; - - Assert(!IsUnderPostmaster); - Assert(IsBootstrapProcessingMode()); + bootstrap_signals(); + BootStrapXLOG(); /* * To ensure that src/common/link-canary.c is linked into the backend, we diff --git a/src/backend/main/main.c b/src/backend/main/main.c index e58e24a6465..78ec85861e9 100644 --- a/src/backend/main/main.c +++ b/src/backend/main/main.c @@ -198,7 +198,7 @@ main(int argc, char *argv[]) #endif if (argc > 1 && strcmp(argv[1], "--boot") == 0) - AuxiliaryProcessMain(argc, argv); /* does not return */ + BootstrapModeMain(argc, argv); /* does not return */ else if (argc > 1 && strcmp(argv[1], "--describe-config") == 0) GucInfoMain(); /* does not return */ else if (argc > 1 && strcmp(argv[1], "--single") == 0) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index df4b115c1e6..ace6eeb4171 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -5020,6 +5020,10 @@ SubPostmasterMain(int argc, char *argv[]) } if (strcmp(argv[1], "--forkaux") == 0) { + AuxProcType auxtype; + + Assert(argc == 4); + /* Restore basic shared memory pointers */ InitShmemAccess(UsedShmemSegAddr); @@ -5029,7 +5033,8 @@ SubPostmasterMain(int argc, char *argv[]) /* Attach process to shared data structures */ CreateSharedMemoryAndSemaphores(); - AuxiliaryProcessMain(argc - 2, argv + 2); /* does not return */ + auxtype = atoi(argv[3]); + AuxiliaryProcessMain(auxtype); /* does not return */ } if (strcmp(argv[1], "--forkavlauncher") == 0) { @@ -5417,28 +5422,28 @@ static pid_t StartChildProcess(AuxProcType type) { pid_t pid; - char *av[10]; - int ac = 0; - char typebuf[32]; - - /* - * Set up command-line arguments for subprocess - */ - av[ac++] = "postgres"; #ifdef EXEC_BACKEND - av[ac++] = "--forkaux"; - av[ac++] = NULL; /* filled in by postmaster_forkexec */ -#endif + { + char *av[10]; + int ac = 0; + char typebuf[32]; - snprintf(typebuf, sizeof(typebuf), "-x%d", type); - av[ac++] = typebuf; + /* + * Set up command-line arguments for subprocess + */ + av[ac++] = "postgres"; + av[ac++] = "--forkaux"; + av[ac++] = NULL; /* filled in by postmaster_forkexec */ - av[ac] = NULL; - Assert(ac < lengthof(av)); + snprintf(typebuf, sizeof(typebuf), "%d", type); + av[ac++] = typebuf; -#ifdef EXEC_BACKEND - pid = postmaster_forkexec(ac, av); + av[ac] = NULL; + Assert(ac < lengthof(av)); + + pid = postmaster_forkexec(ac, av); + } #else /* !EXEC_BACKEND */ pid = fork_process(); @@ -5454,7 +5459,7 @@ StartChildProcess(AuxProcType type) MemoryContextDelete(PostmasterContext); PostmasterContext = NULL; - AuxiliaryProcessMain(ac, av); /* does not return */ + AuxiliaryProcessMain(type); /* does not return */ } #endif /* EXEC_BACKEND */ -- 2.32.0.rc2
>From 1f8ebe0c0f42250fead6b37f0f5328ea3ddd7060 Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Sun, 1 Aug 2021 14:17:38 -0700 Subject: [PATCH v1 03/10] process startup: auxprocess: reindent block Kept separate for ease of review. Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- src/backend/bootstrap/bootstrap.c | 67 +++++++++++++++---------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index d4f341937dc..aac65a86aca 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -236,48 +236,47 @@ AuxiliaryProcessMain(AuxProcType auxtype) * pushups, but there are a couple of things that need to get lit up even * in an auxiliary process. */ - { - /* - * Create a PGPROC so we can use LWLocks. In the EXEC_BACKEND case, - * this was already done by SubPostmasterMain(). - */ + + /* + * Create a PGPROC so we can use LWLocks. In the EXEC_BACKEND case, + * this was already done by SubPostmasterMain(). + */ #ifndef EXEC_BACKEND - InitAuxiliaryProcess(); + InitAuxiliaryProcess(); #endif - /* - * Assign the ProcSignalSlot for an auxiliary process. Since it - * doesn't have a BackendId, the slot is statically allocated based on - * the auxiliary process type (MyAuxProcType). Backends use slots - * indexed in the range from 1 to MaxBackends (inclusive), so we use - * MaxBackends + AuxProcType + 1 as the index of the slot for an - * auxiliary process. - * - * This will need rethinking if we ever want more than one of a - * particular auxiliary process type. - */ - ProcSignalInit(MaxBackends + MyAuxProcType + 1); + /* + * Assign the ProcSignalSlot for an auxiliary process. Since it + * doesn't have a BackendId, the slot is statically allocated based on + * the auxiliary process type (MyAuxProcType). Backends use slots + * indexed in the range from 1 to MaxBackends (inclusive), so we use + * MaxBackends + AuxProcType + 1 as the index of the slot for an + * auxiliary process. + * + * This will need rethinking if we ever want more than one of a + * particular auxiliary process type. + */ + ProcSignalInit(MaxBackends + MyAuxProcType + 1); - /* finish setting up bufmgr.c */ - InitBufferPoolBackend(); + /* finish setting up bufmgr.c */ + InitBufferPoolBackend(); - /* - * Auxiliary processes don't run transactions, but they may need a - * resource owner anyway to manage buffer pins acquired outside - * transactions (and, perhaps, other things in future). - */ - CreateAuxProcessResourceOwner(); + /* + * Auxiliary processes don't run transactions, but they may need a + * resource owner anyway to manage buffer pins acquired outside + * transactions (and, perhaps, other things in future). + */ + CreateAuxProcessResourceOwner(); - /* Initialize statistics reporting */ - pgstat_initialize(); + /* Initialize statistics reporting */ + pgstat_initialize(); - /* Initialize backend status information */ - pgstat_beinit(); - pgstat_bestart(); + /* Initialize backend status information */ + pgstat_beinit(); + pgstat_bestart(); - /* register a before-shutdown callback for LWLock cleanup */ - before_shmem_exit(ShutdownAuxiliaryProcess, 0); - } + /* register a before-shutdown callback for LWLock cleanup */ + before_shmem_exit(ShutdownAuxiliaryProcess, 0); SetProcessingMode(NormalProcessing); -- 2.32.0.rc2
>From ec9ad35c93eada5e0041de22c61e1b87292d9335 Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Sun, 1 Aug 2021 21:17:56 -0700 Subject: [PATCH v1 04/10] process startup: Move AuxiliaryProcessMain into its own file. Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- src/include/bootstrap/bootstrap.h | 2 - src/include/miscadmin.h | 2 +- src/include/postmaster/auxprocess.h | 21 +++ src/backend/bootstrap/bootstrap.c | 158 ---------------------- src/backend/postmaster/Makefile | 1 + src/backend/postmaster/auxprocess.c | 196 ++++++++++++++++++++++++++++ src/backend/postmaster/postmaster.c | 2 +- 7 files changed, 220 insertions(+), 162 deletions(-) create mode 100644 src/include/postmaster/auxprocess.h create mode 100644 src/backend/postmaster/auxprocess.c diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h index 0f8762afaf8..a9829124104 100644 --- a/src/include/bootstrap/bootstrap.h +++ b/src/include/bootstrap/bootstrap.h @@ -15,7 +15,6 @@ #define BOOTSTRAP_H #include "nodes/execnodes.h" -#include "miscadmin.h" /* @@ -34,7 +33,6 @@ extern int numattr; extern void BootstrapModeMain(int argc, char *argv[]) pg_attribute_noreturn(); -extern void AuxiliaryProcessMain(AuxProcType auxtype) pg_attribute_noreturn(); extern void closerel(char *name); extern void boot_openrel(char *name); diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 68d840d6996..1b7422d6366 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -421,7 +421,7 @@ extern ProcessingMode Mode; /* * Auxiliary-process type identifiers. These used to be in bootstrap.h * but it seems saner to have them here, with the ProcessingMode stuff. - * The MyAuxProcType global is defined and set in bootstrap.c. + * The MyAuxProcType global is defined and set in auxprocess.c. */ typedef enum diff --git a/src/include/postmaster/auxprocess.h b/src/include/postmaster/auxprocess.h new file mode 100644 index 00000000000..ec3379d5ee4 --- /dev/null +++ b/src/include/postmaster/auxprocess.h @@ -0,0 +1,21 @@ +/*------------------------------------------------------------------------- + * + * auxprocess.h + * include file for functions related to auxiliary processes. + * + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/postmaster/auxprocess.h + * + *------------------------------------------------------------------------- + */ +#ifndef AUXPROCESS_H +#define AUXPROCESS_H + +#include "miscadmin.h" + +extern void AuxiliaryProcessMain(AuxProcType auxtype) pg_attribute_noreturn(); + +#endif /* AUXPROCESS_H */ diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index aac65a86aca..5c736bb7786 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -33,11 +33,6 @@ #include "miscadmin.h" #include "nodes/makefuncs.h" #include "pg_getopt.h" -#include "pgstat.h" -#include "postmaster/bgwriter.h" -#include "postmaster/startup.h" -#include "postmaster/walwriter.h" -#include "replication/walreceiver.h" #include "storage/bufmgr.h" #include "storage/bufpage.h" #include "storage/condition_variable.h" @@ -47,7 +42,6 @@ #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/memutils.h" -#include "utils/ps_status.h" #include "utils/rel.h" #include "utils/relmapper.h" @@ -56,7 +50,6 @@ uint32 bootstrap_data_checksum_version = 0; /* No checksum */ static void CheckerModeMain(void); static void bootstrap_signals(void); -static void ShutdownAuxiliaryProcess(int code, Datum arg); static Form_pg_attribute AllocateAttribute(void); static void populate_typ_list(void); static Oid gettype(char *type); @@ -67,8 +60,6 @@ static void cleanup(void); * ---------------- */ -AuxProcType MyAuxProcType = NotAnAuxProcess; /* declared in miscadmin.h */ - Relation boot_reldesc; /* current relation descriptor */ Form_pg_attribute attrtypes[MAXATTR]; /* points to attribute info */ @@ -184,140 +175,6 @@ typedef struct _IndexList static IndexList *ILHead = NULL; -/* - * AuxiliaryProcessMain - * - * The main entry point for auxiliary processes, such as the bgwriter, - * walwriter, walreceiver, bootstrapper and the shared memory checker code. - * - * This code is here just because of historical reasons. - */ -void -AuxiliaryProcessMain(AuxProcType auxtype) -{ - Assert(IsUnderPostmaster); - - MyAuxProcType = auxtype; - - switch (MyAuxProcType) - { - case StartupProcess: - MyBackendType = B_STARTUP; - break; - case ArchiverProcess: - MyBackendType = B_ARCHIVER; - break; - case BgWriterProcess: - MyBackendType = B_BG_WRITER; - break; - case CheckpointerProcess: - MyBackendType = B_CHECKPOINTER; - break; - case WalWriterProcess: - MyBackendType = B_WAL_WRITER; - break; - case WalReceiverProcess: - MyBackendType = B_WAL_RECEIVER; - break; - default: - elog(ERROR, "something has gone wrong"); - MyBackendType = B_INVALID; - } - - init_ps_display(NULL); - - SetProcessingMode(BootstrapProcessing); - IgnoreSystemIndexes = true; - - BaseInit(); - - /* - * As an auxiliary process, we aren't going to do the full InitPostgres - * pushups, but there are a couple of things that need to get lit up even - * in an auxiliary process. - */ - - /* - * Create a PGPROC so we can use LWLocks. In the EXEC_BACKEND case, - * this was already done by SubPostmasterMain(). - */ -#ifndef EXEC_BACKEND - InitAuxiliaryProcess(); -#endif - - /* - * Assign the ProcSignalSlot for an auxiliary process. Since it - * doesn't have a BackendId, the slot is statically allocated based on - * the auxiliary process type (MyAuxProcType). Backends use slots - * indexed in the range from 1 to MaxBackends (inclusive), so we use - * MaxBackends + AuxProcType + 1 as the index of the slot for an - * auxiliary process. - * - * This will need rethinking if we ever want more than one of a - * particular auxiliary process type. - */ - ProcSignalInit(MaxBackends + MyAuxProcType + 1); - - /* finish setting up bufmgr.c */ - InitBufferPoolBackend(); - - /* - * Auxiliary processes don't run transactions, but they may need a - * resource owner anyway to manage buffer pins acquired outside - * transactions (and, perhaps, other things in future). - */ - CreateAuxProcessResourceOwner(); - - /* Initialize statistics reporting */ - pgstat_initialize(); - - /* Initialize backend status information */ - pgstat_beinit(); - pgstat_bestart(); - - /* register a before-shutdown callback for LWLock cleanup */ - before_shmem_exit(ShutdownAuxiliaryProcess, 0); - - SetProcessingMode(NormalProcessing); - - switch (MyAuxProcType) - { - case CheckerProcess: - case BootstrapProcess: - pg_unreachable(); - break; - - case StartupProcess: - StartupProcessMain(); - proc_exit(1); - - case ArchiverProcess: - PgArchiverMain(); - proc_exit(1); - - case BgWriterProcess: - BackgroundWriterMain(); - proc_exit(1); - - case CheckpointerProcess: - CheckpointerMain(); - proc_exit(1); - - case WalWriterProcess: - InitXLOGAccess(); - WalWriterMain(); - proc_exit(1); - - case WalReceiverProcess: - WalReceiverMain(); - proc_exit(1); - - default: - elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType); - proc_exit(1); - } -} - /* * In shared memory checker mode, all we really want to do is create shared * memory and semaphores (just to prove we can do it with the current GUC @@ -551,21 +408,6 @@ bootstrap_signals(void) pqsignal(SIGQUIT, SIG_DFL); } -/* - * Begin shutdown of an auxiliary process. This is approximately the equivalent - * of ShutdownPostgres() in postinit.c. We can't run transactions in an - * auxiliary process, so most of the work of AbortTransaction() is not needed, - * but we do need to make sure we've released any LWLocks we are holding. - * (This is only critical during an error exit.) - */ -static void -ShutdownAuxiliaryProcess(int code, Datum arg) -{ - LWLockReleaseAll(); - ConditionVariableCancelSleep(); - pgstat_report_wait_end(); -} - /* ---------------------------------------------------------------- * MANUAL BACKEND INTERACTIVE INTERFACE COMMANDS * ---------------------------------------------------------------- diff --git a/src/backend/postmaster/Makefile b/src/backend/postmaster/Makefile index bfdf6a833db..787c6a2c3bf 100644 --- a/src/backend/postmaster/Makefile +++ b/src/backend/postmaster/Makefile @@ -14,6 +14,7 @@ include $(top_builddir)/src/Makefile.global OBJS = \ autovacuum.o \ + auxprocess.o \ bgworker.o \ bgwriter.o \ checkpointer.o \ diff --git a/src/backend/postmaster/auxprocess.c b/src/backend/postmaster/auxprocess.c new file mode 100644 index 00000000000..e580ad7cbf9 --- /dev/null +++ b/src/backend/postmaster/auxprocess.c @@ -0,0 +1,196 @@ +/*------------------------------------------------------------------------- + * + * auxprocess.c + * -- + * + * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/postmaster/auxprocess.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#include <unistd.h> +#include <signal.h> + +#include "libpq/pqsignal.h" +#include "miscadmin.h" +#include "pgstat.h" +#include "postmaster/auxprocess.h" +#include "postmaster/bgwriter.h" +#include "postmaster/startup.h" +#include "postmaster/walwriter.h" +#include "replication/walreceiver.h" +#include "storage/bufmgr.h" +#include "storage/bufpage.h" +#include "storage/condition_variable.h" +#include "storage/ipc.h" +#include "storage/proc.h" +#include "tcop/tcopprot.h" +#include "utils/memutils.h" +#include "utils/ps_status.h" +#include "utils/rel.h" + + +static void ShutdownAuxiliaryProcess(int code, Datum arg); + + +/* ---------------- + * global variables + * ---------------- + */ + +AuxProcType MyAuxProcType = NotAnAuxProcess; /* declared in miscadmin.h */ + + +/* + * AuxiliaryProcessMain + * + * The main entry point for auxiliary processes, such as the bgwriter, + * walwriter, walreceiver, bootstrapper and the shared memory checker code. + * + * This code is here just because of historical reasons. + */ +void +AuxiliaryProcessMain(AuxProcType auxtype) +{ + Assert(IsUnderPostmaster); + + MyAuxProcType = auxtype; + + switch (MyAuxProcType) + { + case StartupProcess: + MyBackendType = B_STARTUP; + break; + case ArchiverProcess: + MyBackendType = B_ARCHIVER; + break; + case BgWriterProcess: + MyBackendType = B_BG_WRITER; + break; + case CheckpointerProcess: + MyBackendType = B_CHECKPOINTER; + break; + case WalWriterProcess: + MyBackendType = B_WAL_WRITER; + break; + case WalReceiverProcess: + MyBackendType = B_WAL_RECEIVER; + break; + default: + elog(ERROR, "something has gone wrong"); + MyBackendType = B_INVALID; + } + + init_ps_display(NULL); + + SetProcessingMode(BootstrapProcessing); + IgnoreSystemIndexes = true; + + BaseInit(); + + /* + * As an auxiliary process, we aren't going to do the full InitPostgres + * pushups, but there are a couple of things that need to get lit up even + * in an auxiliary process. + */ + + /* + * Create a PGPROC so we can use LWLocks. In the EXEC_BACKEND case, + * this was already done by SubPostmasterMain(). + */ +#ifndef EXEC_BACKEND + InitAuxiliaryProcess(); +#endif + + /* + * Assign the ProcSignalSlot for an auxiliary process. Since it + * doesn't have a BackendId, the slot is statically allocated based on + * the auxiliary process type (MyAuxProcType). Backends use slots + * indexed in the range from 1 to MaxBackends (inclusive), so we use + * MaxBackends + AuxProcType + 1 as the index of the slot for an + * auxiliary process. + * + * This will need rethinking if we ever want more than one of a + * particular auxiliary process type. + */ + ProcSignalInit(MaxBackends + MyAuxProcType + 1); + + /* finish setting up bufmgr.c */ + InitBufferPoolBackend(); + + /* + * Auxiliary processes don't run transactions, but they may need a + * resource owner anyway to manage buffer pins acquired outside + * transactions (and, perhaps, other things in future). + */ + CreateAuxProcessResourceOwner(); + + /* Initialize statistics reporting */ + pgstat_initialize(); + + /* Initialize backend status information */ + pgstat_beinit(); + pgstat_bestart(); + + /* register a before-shutdown callback for LWLock cleanup */ + before_shmem_exit(ShutdownAuxiliaryProcess, 0); + + SetProcessingMode(NormalProcessing); + + switch (MyAuxProcType) + { + case CheckerProcess: + case BootstrapProcess: + pg_unreachable(); + break; + + case StartupProcess: + StartupProcessMain(); + proc_exit(1); + + case ArchiverProcess: + PgArchiverMain(); + proc_exit(1); + + case BgWriterProcess: + BackgroundWriterMain(); + proc_exit(1); + + case CheckpointerProcess: + CheckpointerMain(); + proc_exit(1); + + case WalWriterProcess: + InitXLOGAccess(); + WalWriterMain(); + proc_exit(1); + + case WalReceiverProcess: + WalReceiverMain(); + proc_exit(1); + + default: + elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType); + proc_exit(1); + } +} + +/* + * Begin shutdown of an auxiliary process. This is approximately the equivalent + * of ShutdownPostgres() in postinit.c. We can't run transactions in an + * auxiliary process, so most of the work of AbortTransaction() is not needed, + * but we do need to make sure we've released any LWLocks we are holding. + * (This is only critical during an error exit.) + */ +static void +ShutdownAuxiliaryProcess(int code, Datum arg) +{ + LWLockReleaseAll(); + ConditionVariableCancelSleep(); + pgstat_report_wait_end(); +} diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index ace6eeb4171..cf34831d8fe 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -95,7 +95,6 @@ #include "access/transam.h" #include "access/xlog.h" -#include "bootstrap/bootstrap.h" #include "catalog/pg_control.h" #include "common/file_perm.h" #include "common/ip.h" @@ -109,6 +108,7 @@ #include "pgstat.h" #include "port/pg_bswap.h" #include "postmaster/autovacuum.h" +#include "postmaster/auxprocess.h" #include "postmaster/bgworker_internals.h" #include "postmaster/fork_process.h" #include "postmaster/interrupt.h" -- 2.32.0.rc2
>From 442e44a039a823a46436601610a42ca4576c2a51 Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Sat, 31 Jul 2021 14:23:19 -0700 Subject: [PATCH v1 05/10] process startup: Centralize pgwin32_signal_initialize() calls. Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- src/backend/main/main.c | 31 ++++++++++------------------- src/backend/postmaster/postmaster.c | 9 --------- src/backend/utils/init/miscinit.c | 19 +++++++++++++++++- 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/src/backend/main/main.c b/src/backend/main/main.c index 78ec85861e9..51494f6cc4b 100644 --- a/src/backend/main/main.c +++ b/src/backend/main/main.c @@ -181,33 +181,22 @@ main(int argc, char *argv[]) * Dispatch to one of various subprograms depending on first argument. */ -#ifdef EXEC_BACKEND - if (argc > 1 && strncmp(argv[1], "--fork", 6) == 0) - SubPostmasterMain(argc, argv); /* does not return */ -#endif - -#ifdef WIN32 - - /* - * Start our win32 signal implementation - * - * SubPostmasterMain() will do this for itself, but the remaining modes - * need it here - */ - pgwin32_signal_initialize(); -#endif - if (argc > 1 && strcmp(argv[1], "--boot") == 0) - BootstrapModeMain(argc, argv); /* does not return */ + BootstrapModeMain(argc, argv); +#ifdef EXEC_BACKEND + else if (argc > 1 && strncmp(argv[1], "--fork", 6) == 0) + SubPostmasterMain(argc, argv); +#endif else if (argc > 1 && strcmp(argv[1], "--describe-config") == 0) - GucInfoMain(); /* does not return */ + GucInfoMain(); else if (argc > 1 && strcmp(argv[1], "--single") == 0) PostgresMain(argc, argv, NULL, /* no dbname */ - strdup(get_user_name_or_exit(progname))); /* does not return */ + strdup(get_user_name_or_exit(progname))); else - PostmasterMain(argc, argv); /* does not return */ - abort(); /* should not get here */ + PostmasterMain(argc, argv); + /* the functions above should not return */ + abort(); } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index cf34831d8fe..46c6d76ccf9 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -4899,15 +4899,6 @@ SubPostmasterMain(int argc, char *argv[]) /* Close the postmaster's sockets (as soon as we know them) */ ClosePostmasterPorts(strcmp(argv[1], "--forklog") == 0); - /* - * Start our win32 signal implementation. This has to be done after we - * read the backend variables, because we need to pick up the signal pipe - * from the parent process. - */ -#ifdef WIN32 - pgwin32_signal_initialize(); -#endif - /* Setup as postmaster child */ InitPostmasterChild(); diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 8b73850d0df..88801374b57 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -87,13 +87,23 @@ bool IgnoreSystemIndexes = false; /* * Initialize the basic environment for a postmaster child * - * Should be called as early as possible after the child's startup. + * Should be called as early as possible after the child's startup. However, + * on EXEC_BACKEND builds it does need to be after read_backend_variables(). */ void InitPostmasterChild(void) { IsUnderPostmaster = true; /* we are a postmaster subprocess now */ + /* + * Start our win32 signal implementation. This has to be done after we + * read the backend variables, because we need to pick up the signal pipe + * from the parent process. + */ +#ifdef WIN32 + pgwin32_signal_initialize(); +#endif + /* * Set reference point for stack-depth checking. We re-do that even in the * !EXEC_BACKEND case, because there are some edge cases where processes @@ -166,6 +176,13 @@ InitStandaloneProcess(const char *argv0) { Assert(!IsPostmasterEnvironment); + /* + * Start our win32 signal implementation + */ +#ifdef WIN32 + pgwin32_signal_initialize(); +#endif + InitProcessGlobals(); /* Initialize process-local latch support */ -- 2.32.0.rc2
>From 030fe91346fc1e6bd916cf043e30f4a60c5b55e0 Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Sun, 1 Aug 2021 14:39:25 -0700 Subject: [PATCH v1 06/10] process startup: Rename StartChildProcess to StartAuxiliaryProcess. The prior name was confusing because postmaster.c has many types of children, but StartChildProcess was only used for aux processes. Even more confusing, there's SignalChildren/SignalSomeChildren(), which do *not* target aux processes. Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- src/backend/postmaster/postmaster.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 46c6d76ccf9..65bc4dcbbd6 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -433,7 +433,7 @@ static int CountChildren(int target); static bool assign_backendlist_entry(RegisteredBgWorker *rw); static void maybe_start_bgworkers(void); static bool CreateOptsFile(int argc, char *argv[], char *fullprogname); -static pid_t StartChildProcess(AuxProcType type); +static pid_t StartAuxiliaryProcess(AuxProcType type); static void StartAutovacuumWorker(void); static void MaybeStartWalReceiver(void); static void InitPostmasterDeathWatchHandle(void); @@ -551,12 +551,12 @@ static void ShmemBackendArrayAdd(Backend *bn); static void ShmemBackendArrayRemove(Backend *bn); #endif /* EXEC_BACKEND */ -#define StartupDataBase() StartChildProcess(StartupProcess) -#define StartArchiver() StartChildProcess(ArchiverProcess) -#define StartBackgroundWriter() StartChildProcess(BgWriterProcess) -#define StartCheckpointer() StartChildProcess(CheckpointerProcess) -#define StartWalWriter() StartChildProcess(WalWriterProcess) -#define StartWalReceiver() StartChildProcess(WalReceiverProcess) +#define StartupDataBase() StartAuxiliaryProcess(StartupProcess) +#define StartArchiver() StartAuxiliaryProcess(ArchiverProcess) +#define StartBackgroundWriter() StartAuxiliaryProcess(BgWriterProcess) +#define StartCheckpointer() StartAuxiliaryProcess(CheckpointerProcess) +#define StartWalWriter() StartAuxiliaryProcess(WalWriterProcess) +#define StartWalReceiver() StartAuxiliaryProcess(WalReceiverProcess) /* Macros to check exit status of a child process */ #define EXIT_STATUS_0(st) ((st) == 0) @@ -5401,16 +5401,16 @@ CountChildren(int target) /* - * StartChildProcess -- start an auxiliary process for the postmaster + * StartAuxiliaryProcess -- start an auxiliary process for the postmaster * * "type" determines what kind of child will be started. All child types * initially go to AuxiliaryProcessMain, which will handle common setup. * - * Return value of StartChildProcess is subprocess' PID, or 0 if failed + * Return value of StartAuxiliaryProcess is subprocess' PID, or 0 if failed * to start subprocess. */ static pid_t -StartChildProcess(AuxProcType type) +StartAuxiliaryProcess(AuxProcType type) { pid_t pid; -- 2.32.0.rc2
>From 7e1d51ad005851584e6aa021d6d0763cd57acc9a Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Sun, 1 Aug 2021 15:25:25 -0700 Subject: [PATCH v1 07/10] process startup: Remove bootstrap / checker modes from AuxProcType. Neither is actually initialized as an auxiliary process, so it doesn't make sense to reserve a PGPROC etc for them. Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- src/include/bootstrap/bootstrap.h | 2 +- src/include/miscadmin.h | 4 +--- src/backend/bootstrap/bootstrap.c | 24 ++++++------------------ src/backend/main/main.c | 8 +++++--- src/backend/postmaster/auxprocess.c | 5 ----- src/bin/initdb/initdb.c | 6 +++--- 6 files changed, 16 insertions(+), 33 deletions(-) diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h index a9829124104..5bef4f56244 100644 --- a/src/include/bootstrap/bootstrap.h +++ b/src/include/bootstrap/bootstrap.h @@ -32,7 +32,7 @@ extern Form_pg_attribute attrtypes[MAXATTR]; extern int numattr; -extern void BootstrapModeMain(int argc, char *argv[]) pg_attribute_noreturn(); +extern void BootstrapModeMain(int argc, char *argv[], bool check_mode) pg_attribute_noreturn(); extern void closerel(char *name); extern void boot_openrel(char *name); diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 1b7422d6366..58f7fd28c95 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -427,9 +427,7 @@ extern ProcessingMode Mode; typedef enum { NotAnAuxProcess = -1, - CheckerProcess = 0, - BootstrapProcess, - StartupProcess, + StartupProcess = 0, BgWriterProcess, ArchiverProcess, CheckpointerProcess, diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 5c736bb7786..80c90ea9d9b 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -195,7 +195,7 @@ CheckerModeMain(void) * commands in a special bootstrap language. */ void -BootstrapModeMain(int argc, char *argv[]) +BootstrapModeMain(int argc, char *argv[], bool check_mode) { int i; char *progname = argv[0]; @@ -209,16 +209,14 @@ BootstrapModeMain(int argc, char *argv[]) /* Set defaults, to be overridden by explicit options below */ InitializeGUCOptions(); - /* an initial --boot should be present */ + /* an initial --boot or --check should be present */ Assert(argc == 1 - || strcmp(argv[1], "--boot") != 0); + || strcmp(argv[1], "--boot") != 0 + || strcmp(argv[1], "--check") != 0); argv++; argc--; - /* If no -x argument, we are a CheckerProcess */ - MyAuxProcType = CheckerProcess; - - while ((flag = getopt(argc, argv, "B:c:d:D:Fkr:x:X:-:")) != -1) + while ((flag = getopt(argc, argv, "B:c:d:D:Fkr:X:-:")) != -1) { switch (flag) { @@ -250,16 +248,6 @@ BootstrapModeMain(int argc, char *argv[]) case 'r': strlcpy(OutputFileName, optarg, MAXPGPATH); break; - case 'x': - MyAuxProcType = atoi(optarg); - if (MyAuxProcType != CheckerProcess && - MyAuxProcType != BootstrapProcess) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("-x %s is invalid", optarg))); - } - break; case 'X': { int WalSegSz = strtoul(optarg, NULL, 0); @@ -334,7 +322,7 @@ BootstrapModeMain(int argc, char *argv[]) BaseInit(); /* FIXME: Move out. New top-level mode? */ - if (MyAuxProcType == CheckerProcess) + if (check_mode) { SetProcessingMode(NormalProcessing); CheckerModeMain(); diff --git a/src/backend/main/main.c b/src/backend/main/main.c index 51494f6cc4b..3a2a0d598cd 100644 --- a/src/backend/main/main.c +++ b/src/backend/main/main.c @@ -181,8 +181,10 @@ main(int argc, char *argv[]) * Dispatch to one of various subprograms depending on first argument. */ - if (argc > 1 && strcmp(argv[1], "--boot") == 0) - BootstrapModeMain(argc, argv); + if (argc > 1 && strcmp(argv[1], "--check") == 0) + BootstrapModeMain(argc, argv, true); + else if (argc > 1 && strcmp(argv[1], "--boot") == 0) + BootstrapModeMain(argc, argv, false); #ifdef EXEC_BACKEND else if (argc > 1 && strncmp(argv[1], "--fork", 6) == 0) SubPostmasterMain(argc, argv); @@ -339,9 +341,9 @@ help(const char *progname) printf(_("\nOptions for bootstrapping mode:\n")); printf(_(" --boot selects bootstrapping mode (must be first argument)\n")); + printf(_(" --check selects check mode (must be first argument)\n")); printf(_(" DBNAME database name (mandatory argument in bootstrapping mode)\n")); printf(_(" -r FILENAME send stdout and stderr to given file\n")); - printf(_(" -x NUM internal use\n")); printf(_("\nPlease read the documentation for the complete list of run-time\n" "configuration settings and how to set them on the command line or in\n" diff --git a/src/backend/postmaster/auxprocess.c b/src/backend/postmaster/auxprocess.c index e580ad7cbf9..7906c327923 100644 --- a/src/backend/postmaster/auxprocess.c +++ b/src/backend/postmaster/auxprocess.c @@ -144,11 +144,6 @@ AuxiliaryProcessMain(AuxProcType auxtype) switch (MyAuxProcType) { - case CheckerProcess: - case BootstrapProcess: - pg_unreachable(); - break; - case StartupProcess: StartupProcessMain(); proc_exit(1); diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 994bf07f3ba..5e84c7bb20e 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -965,7 +965,7 @@ test_config_settings(void) test_buffs = MIN_BUFS_FOR_CONNS(test_conns); snprintf(cmd, sizeof(cmd), - "\"%s\" --boot -x0 %s %s " + "\"%s\" --check %s %s " "-c max_connections=%d " "-c shared_buffers=%d " "-c dynamic_shared_memory_type=%s " @@ -1001,7 +1001,7 @@ test_config_settings(void) } snprintf(cmd, sizeof(cmd), - "\"%s\" --boot -x0 %s %s " + "\"%s\" --check %s %s " "-c max_connections=%d " "-c shared_buffers=%d " "-c dynamic_shared_memory_type=%s " @@ -1406,7 +1406,7 @@ bootstrap_template1(void) unsetenv("PGCLIENTENCODING"); snprintf(cmd, sizeof(cmd), - "\"%s\" --boot -x1 -X %u %s %s %s %s", + "\"%s\" --boot -X %u %s %s %s %s", backend_exec, wal_segment_size_mb * (1024 * 1024), data_checksums ? "-k" : "", -- 2.32.0.rc2
>From 05b4cb635686e9d849069c641afcd0c69e6909ec Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Mon, 2 Aug 2021 00:36:46 -0700 Subject: [PATCH v1 08/10] process startup: Always call Init[Auxiliary]Process() before BaseInit(). For EXEC_BACKEND InitProcess()/InitAuxiliaryProcess() needs to have been called well before we call BaseInit(), as SubPostmasterMain() needs LWLocks to work. Having the order of initialization differ between platforms makes it unnecessarily harder to understand the system. To be able to do so, BaseInit() cannot trigger CreateSharedMemoryAndSemaphores() anymore. Which seems like a cleanup anyway. Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- src/include/storage/bufmgr.h | 1 - src/backend/bootstrap/bootstrap.c | 18 +++++++------- src/backend/postmaster/autovacuum.c | 12 +++++----- src/backend/postmaster/auxprocess.c | 7 ++---- src/backend/postmaster/bgworker.c | 16 ++++++------- src/backend/storage/buffer/bufmgr.c | 23 ++++-------------- src/backend/tcop/postgres.c | 8 ++++--- src/backend/utils/init/postinit.c | 37 +++-------------------------- 8 files changed, 39 insertions(+), 83 deletions(-) diff --git a/src/include/storage/bufmgr.h b/src/include/storage/bufmgr.h index aa64fb42ec4..cfce23ecbc8 100644 --- a/src/include/storage/bufmgr.h +++ b/src/include/storage/bufmgr.h @@ -194,7 +194,6 @@ extern Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation, extern void InitBufferPool(void); extern void InitBufferPoolAccess(void); -extern void InitBufferPoolBackend(void); extern void AtEOXact_Buffers(bool isCommit); extern void PrintBufferLeakWarning(Buffer buffer); extern void CheckPointBuffers(int flags); diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c index 80c90ea9d9b..18a37b54961 100644 --- a/src/backend/bootstrap/bootstrap.c +++ b/src/backend/bootstrap/bootstrap.c @@ -178,8 +178,8 @@ static IndexList *ILHead = NULL; /* * In shared memory checker mode, all we really want to do is create shared * memory and semaphores (just to prove we can do it with the current GUC - * settings). Since, in fact, that was already done by BaseInit(), - * we have nothing more to do here. + * settings). Since, in fact, that was already done by + * CreateSharedMemoryAndSemaphores(), we have nothing more to do here. */ static void CheckerModeMain(void) @@ -319,7 +319,7 @@ BootstrapModeMain(int argc, char *argv[], bool check_mode) InitializeMaxBackends(); - BaseInit(); + CreateSharedMemoryAndSemaphores(); /* FIXME: Move out. New top-level mode? */ if (check_mode) @@ -329,6 +329,13 @@ BootstrapModeMain(int argc, char *argv[], bool check_mode) abort(); } + /* + * Do backend-like initialization for bootstrap mode + */ + InitProcess(); + + BaseInit(); + bootstrap_signals(); BootStrapXLOG(); @@ -339,11 +346,6 @@ BootstrapModeMain(int argc, char *argv[], bool check_mode) if (pg_link_canary_is_frontend()) elog(ERROR, "backend is incorrectly linked to frontend functions"); - /* - * Do backend-like initialization for bootstrap mode - */ - InitProcess(); - InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL, false); /* Initialize stuff for bootstrap-file processing */ diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 912ef9cb54c..59d348b062f 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -469,9 +469,6 @@ AutoVacLauncherMain(int argc, char *argv[]) pqsignal(SIGFPE, FloatExceptionHandler); pqsignal(SIGCHLD, SIG_DFL); - /* Early initialization */ - BaseInit(); - /* * Create a per-backend PGPROC struct in shared memory, except in the * EXEC_BACKEND case where this was done in SubPostmasterMain. We must do @@ -482,6 +479,9 @@ AutoVacLauncherMain(int argc, char *argv[]) InitProcess(); #endif + /* Early initialization */ + BaseInit(); + InitPostgres(NULL, InvalidOid, NULL, InvalidOid, NULL, false); SetProcessingMode(NormalProcessing); @@ -1547,9 +1547,6 @@ AutoVacWorkerMain(int argc, char *argv[]) pqsignal(SIGFPE, FloatExceptionHandler); pqsignal(SIGCHLD, SIG_DFL); - /* Early initialization */ - BaseInit(); - /* * Create a per-backend PGPROC struct in shared memory, except in the * EXEC_BACKEND case where this was done in SubPostmasterMain. We must do @@ -1560,6 +1557,9 @@ AutoVacWorkerMain(int argc, char *argv[]) InitProcess(); #endif + /* Early initialization */ + BaseInit(); + /* * If an exception is encountered, processing resumes here. * diff --git a/src/backend/postmaster/auxprocess.c b/src/backend/postmaster/auxprocess.c index 7906c327923..07de567a5b0 100644 --- a/src/backend/postmaster/auxprocess.c +++ b/src/backend/postmaster/auxprocess.c @@ -91,8 +91,6 @@ AuxiliaryProcessMain(AuxProcType auxtype) SetProcessingMode(BootstrapProcessing); IgnoreSystemIndexes = true; - BaseInit(); - /* * As an auxiliary process, we aren't going to do the full InitPostgres * pushups, but there are a couple of things that need to get lit up even @@ -107,6 +105,8 @@ AuxiliaryProcessMain(AuxProcType auxtype) InitAuxiliaryProcess(); #endif + BaseInit(); + /* * Assign the ProcSignalSlot for an auxiliary process. Since it * doesn't have a BackendId, the slot is statically allocated based on @@ -120,9 +120,6 @@ AuxiliaryProcessMain(AuxProcType auxtype) */ ProcSignalInit(MaxBackends + MyAuxProcType + 1); - /* finish setting up bufmgr.c */ - InitBufferPoolBackend(); - /* * Auxiliary processes don't run transactions, but they may need a * resource owner anyway to manage buffer pins acquired outside diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c index c40410d73ea..11c4ceddbf6 100644 --- a/src/backend/postmaster/bgworker.c +++ b/src/backend/postmaster/bgworker.c @@ -837,14 +837,6 @@ StartBackgroundWorker(void) */ if (worker->bgw_flags & BGWORKER_SHMEM_ACCESS) { - /* - * Early initialization. Some of this could be useful even for - * background workers that aren't using shared memory, but they can - * call the individual startup routines for those subsystems if - * needed. - */ - BaseInit(); - /* * Create a per-backend PGPROC struct in shared memory, except in the * EXEC_BACKEND case where this was done in SubPostmasterMain. We must @@ -854,6 +846,14 @@ StartBackgroundWorker(void) #ifndef EXEC_BACKEND InitProcess(); #endif + + /* + * Early initialization. Some of this could be useful even for + * background workers that aren't using shared memory, but they can + * call the individual startup routines for those subsystems if + * needed. + */ + BaseInit(); } /* diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 33d99f604ad..8699da7e44b 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -2582,11 +2582,6 @@ AtEOXact_Buffers(bool isCommit) * This is called during backend startup (whether standalone or under the * postmaster). It sets up for this backend's access to the already-existing * buffer pool. - * - * NB: this is called before InitProcess(), so we do not have a PGPROC and - * cannot do LWLockAcquire; hence we can't actually access stuff in - * shared memory yet. We are only initializing local data here. - * (See also InitBufferPoolBackend) */ void InitBufferPoolAccess(void) @@ -2600,20 +2595,12 @@ InitBufferPoolAccess(void) PrivateRefCountHash = hash_create("PrivateRefCount", 100, &hash_ctl, HASH_ELEM | HASH_BLOBS); -} -/* - * InitBufferPoolBackend --- second-stage initialization of a new backend - * - * This is called after we have acquired a PGPROC and so can safely get - * LWLocks. We don't currently need to do anything at this stage ... - * except register a shmem-exit callback. AtProcExit_Buffers needs LWLock - * access, and thereby has to be called at the corresponding phase of - * backend shutdown. - */ -void -InitBufferPoolBackend(void) -{ + /* + * AtProcExit_Buffers needs LWLock access, and thereby has to be called at + * the corresponding phase of backend shutdown. + */ + Assert(MyProc != NULL); on_shmem_exit(AtProcExit_Buffers, 0); } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 530caa520b8..58b5960e27d 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -4050,10 +4050,9 @@ PostgresMain(int argc, char *argv[], /* Initialize MaxBackends (if under postmaster, was done already) */ InitializeMaxBackends(); - } - /* Early initialization */ - BaseInit(); + CreateSharedMemoryAndSemaphores(); + } /* * Create a per-backend PGPROC struct in shared memory, except in the @@ -4068,6 +4067,9 @@ PostgresMain(int argc, char *argv[], InitProcess(); #endif + /* Early initialization */ + BaseInit(); + /* We need to allow SIGINT, etc during the initial transaction */ PG_SETMASK(&UnBlockSig); diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 51d1bbef301..420b246fb13 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -67,7 +67,6 @@ static HeapTuple GetDatabaseTuple(const char *dbname); static HeapTuple GetDatabaseTupleByOid(Oid dboid); static void PerformAuthentication(Port *port); static void CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connections); -static void InitCommunication(void); static void ShutdownPostgres(int code, Datum arg); static void StatementTimeoutHandler(void); static void LockTimeoutHandler(void); @@ -417,31 +416,6 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect } - -/* -------------------------------- - * InitCommunication - * - * This routine initializes stuff needed for ipc, locking, etc. - * it should be called something more informative. - * -------------------------------- - */ -static void -InitCommunication(void) -{ - /* - * initialize shared memory and semaphores appropriately. - */ - if (!IsUnderPostmaster) /* postmaster already did this */ - { - /* - * We're running a postgres bootstrap process or a standalone backend, - * so we need to set up shmem. - */ - CreateSharedMemoryAndSemaphores(); - } -} - - /* * pg_split_opts -- split a string of options and append it to an argv array * @@ -536,11 +510,11 @@ InitializeMaxBackends(void) void BaseInit(void) { + Assert(MyProc != NULL); + /* - * Attach to shared memory and semaphores, and initialize our - * input/output/debugging file descriptors. + * Initialize our input/output/debugging file descriptors. */ - InitCommunication(); DebugFileOpen(); /* Do local initialization of file, storage and buffer managers */ @@ -624,11 +598,6 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, RegisterTimeout(CLIENT_CONNECTION_CHECK_TIMEOUT, ClientCheckTimeoutHandler); } - /* - * bufmgr needs another initialization call too - */ - InitBufferPoolBackend(); - /* * Initialize local process's access to XLOG. */ -- 2.32.0.rc2
>From aede71587e8e566b0126cf867cb51e9133c96a7e Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Mon, 2 Aug 2021 00:38:53 -0700 Subject: [PATCH v1 09/10] process startup: Do InitProcess() at the same time regardless of EXEC_BACKEND. This is useful because it makes it easier to extract the setup for single user mode into its own function. Author: Reviewed-By: Discussion: https://postgr.es/m/ Backpatch: --- src/backend/postmaster/postmaster.c | 9 +++++++++ src/backend/tcop/postgres.c | 13 +------------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 65bc4dcbbd6..acecb4a5c9d 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -4224,6 +4224,15 @@ BackendStartup(Port *port) /* Perform additional initialization and collect startup packet */ BackendInitialize(port); + /* + * Create a per-backend PGPROC struct in shared memory. We must do + * this before we can use LWLocks. In the !EXEC_BACKEND case (here) + * this could be delayed a bit further, but EXEC_BACKEND needs to do + * stuff with LWLocks before PostgresMain(), so we do it here as well + * for symmetry. + */ + InitProcess(); + /* And run the backend */ BackendRun(port); } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 58b5960e27d..6e22e2634b5 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -4052,20 +4052,9 @@ PostgresMain(int argc, char *argv[], InitializeMaxBackends(); CreateSharedMemoryAndSemaphores(); - } - /* - * Create a per-backend PGPROC struct in shared memory, except in the - * EXEC_BACKEND case where this was done in SubPostmasterMain. We must do - * this before we can use LWLocks (and in the EXEC_BACKEND case we already - * had to do some stuff with LWLocks). - */ -#ifdef EXEC_BACKEND - if (!IsUnderPostmaster) InitProcess(); -#else - InitProcess(); -#endif + } /* Early initialization */ BaseInit(); -- 2.32.0.rc2
>From 53f31c985cbcb241e6543f437556315541a74246 Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Mon, 2 Aug 2021 00:43:18 -0700 Subject: [PATCH v1 10/10] process startup: Split single user code out of PostgresMain(). --- src/include/tcop/tcopprot.h | 5 +- src/backend/main/main.c | 5 +- src/backend/postmaster/postmaster.c | 8 +- src/backend/tcop/postgres.c | 140 +++++++++++++++------------- 4 files changed, 83 insertions(+), 75 deletions(-) diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h index 968345404e5..4c0a0e69cfc 100644 --- a/src/include/tcop/tcopprot.h +++ b/src/include/tcop/tcopprot.h @@ -75,8 +75,9 @@ extern void ProcessClientWriteInterrupt(bool blocked); extern void process_postgres_switches(int argc, char *argv[], GucContext ctx, const char **dbname); -extern void PostgresMain(int argc, char *argv[], - const char *dbname, +extern void PostgresMainSingle(int argc, char *argv[], + const char *username) pg_attribute_noreturn(); +extern void PostgresMain(const char *dbname, const char *username) pg_attribute_noreturn(); extern long get_stack_depth_rlimit(void); extern void ResetUsage(void); diff --git a/src/backend/main/main.c b/src/backend/main/main.c index 3a2a0d598cd..034a1ac1361 100644 --- a/src/backend/main/main.c +++ b/src/backend/main/main.c @@ -192,9 +192,8 @@ main(int argc, char *argv[]) else if (argc > 1 && strcmp(argv[1], "--describe-config") == 0) GucInfoMain(); else if (argc > 1 && strcmp(argv[1], "--single") == 0) - PostgresMain(argc, argv, - NULL, /* no dbname */ - strdup(get_user_name_or_exit(progname))); + PostgresMainSingle(argc, argv, + strdup(get_user_name_or_exit(progname))); else PostmasterMain(argc, argv); /* the functions above should not return */ diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index acecb4a5c9d..424f587d368 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -4500,19 +4500,13 @@ BackendInitialize(Port *port) static void BackendRun(Port *port) { - char *av[2]; - const int ac = 1; - - av[0] = "postgres"; - av[1] = NULL; - /* * Make sure we aren't in PostmasterContext anymore. (We can't delete it * just yet, though, because InitPostgres will need the HBA data.) */ MemoryContextSwitchTo(TopMemoryContext); - PostgresMain(ac, av, port->database_name, port->user_name); + PostgresMain(port->database_name, port->user_name); } diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 6e22e2634b5..382e1629f16 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -3915,40 +3915,28 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx, } -/* ---------------------------------------------------------------- - * PostgresMain - * postgres main loop -- all backends, interactive or otherwise start here +/* + * PostgresMainSingle + * Entry point for single user mode. argc/argv are the command line + * arguments to be used. * - * argc/argv are the command line arguments to be used. (When being forked - * by the postmaster, these are not the original argv array of the process.) - * dbname is the name of the database to connect to, or NULL if the database - * name should be extracted from the command line arguments or defaulted. - * username is the PostgreSQL user name to be used for the session. - * ---------------------------------------------------------------- + * FIXME: comments. */ void -PostgresMain(int argc, char *argv[], - const char *dbname, - const char *username) +PostgresMainSingle(int argc, char *argv[], + const char *username) { - int firstchar; - StringInfoData input_message; - sigjmp_buf local_sigjmp_buf; - volatile bool send_ready_for_query = true; - bool idle_in_transaction_timeout_enabled = false; - bool idle_session_timeout_enabled = false; + const char *dbname = NULL; - /* Initialize startup process environment if necessary. */ - if (!IsUnderPostmaster) - InitStandaloneProcess(argv[0]); + Assert(!IsUnderPostmaster); - SetProcessingMode(InitProcessing); + /* Initialize startup process environment. */ + InitStandaloneProcess(argv[0]); /* * Set default values for command-line options. */ - if (!IsUnderPostmaster) - InitializeGUCOptions(); + InitializeGUCOptions(); /* * Parse command-line options. @@ -3966,12 +3954,71 @@ PostgresMain(int argc, char *argv[], progname))); } - /* Acquire configuration parameters, unless inherited from postmaster */ - if (!IsUnderPostmaster) - { - if (!SelectConfigFiles(userDoption, progname)) - proc_exit(1); - } + /* Acquire configuration parameters */ + if (!SelectConfigFiles(userDoption, progname)) + proc_exit(1); + + /* + * Validate we have been given a reasonable-looking DataDir and change + * into it. + */ + checkDataDir(); + ChangeToDataDir(); + + /* + * Create lockfile for data directory. + */ + CreateDataDirLockFile(false); + + /* read control file (error checking and contains config ) */ + LocalProcessControlFile(false); + + /* Initialize MaxBackends (if under postmaster, was done already) */ + InitializeMaxBackends(); + + CreateSharedMemoryAndSemaphores(); + + /* + * Remember stand-alone backend startup time + */ + PgStartTime = GetCurrentTimestamp(); + + /* + * Create a per-backend PGPROC struct in shared memory. We must do this + * before we can use LWLocks. + */ + InitProcess(); + + /* + * Now that sufficient infrastructure has been initialized, PostgresMain() + * can do the rest. + */ + PostgresMain(dbname, username); +} + + +/* ---------------------------------------------------------------- + * PostgresMain + * postgres main loop -- all backends, interactive or otherwise loop here + * + * dbname is the name of the database to connect to, username is the + * PostgreSQL user name to be used for the session. + * ---------------------------------------------------------------- + */ +void +PostgresMain(const char *dbname, const char *username) +{ + int firstchar; + StringInfoData input_message; + sigjmp_buf local_sigjmp_buf; + volatile bool send_ready_for_query = true; + bool idle_in_transaction_timeout_enabled = false; + bool idle_session_timeout_enabled = false; + + AssertArg(dbname != NULL); + AssertArg(username != NULL); + + SetProcessingMode(InitProcessing); /* * Set up signal handlers. (InitPostmasterChild or InitStandaloneProcess @@ -4029,33 +4076,6 @@ PostgresMain(int argc, char *argv[], * platforms */ } - if (!IsUnderPostmaster) - { - /* - * Validate we have been given a reasonable-looking DataDir (if under - * postmaster, assume postmaster did this already). - */ - checkDataDir(); - - /* Change into DataDir (if under postmaster, was done already) */ - ChangeToDataDir(); - - /* - * Create lockfile for data directory. - */ - CreateDataDirLockFile(false); - - /* read control file (error checking and contains config ) */ - LocalProcessControlFile(false); - - /* Initialize MaxBackends (if under postmaster, was done already) */ - InitializeMaxBackends(); - - CreateSharedMemoryAndSemaphores(); - - InitProcess(); - } - /* Early initialization */ BaseInit(); @@ -4150,12 +4170,6 @@ PostgresMain(int argc, char *argv[], initStringInfo(&row_description_buf); MemoryContextSwitchTo(TopMemoryContext); - /* - * Remember stand-alone backend startup time - */ - if (!IsUnderPostmaster) - PgStartTime = GetCurrentTimestamp(); - /* * POSTGRES main processing loop begins here * -- 2.32.0.rc2