From a6f005d9ea81e1a989353f320149e12281e9fb04 Mon Sep 17 00:00:00 2001 From: Mike Palmiotto Date: Fri, 27 Sep 2019 16:45:57 -0400 Subject: [PATCH 2/8] Add centralized autovac launcher/worker --- src/backend/postmaster/autovacuum.c | 157 ++++---------------------- src/backend/postmaster/postmaster.c | 67 ++++++----- src/include/postmaster/autovacuum.h | 9 +- src/include/postmaster/fork_process.h | 2 + 4 files changed, 70 insertions(+), 165 deletions(-) diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 073f313337..5c3ac1568f 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -134,8 +134,8 @@ int Log_autovacuum_min_duration = -1; #define MAX_AUTOVAC_SLEEPTIME 300 /* seconds */ /* Flags to tell if we are in an autovacuum process */ -static bool am_autovacuum_launcher = false; -static bool am_autovacuum_worker = false; +bool am_autovacuum_launcher = false; +bool am_autovacuum_worker = false; /* Flags set by signal handlers */ static volatile sig_atomic_t got_SIGHUP = false; @@ -303,10 +303,6 @@ static WorkerInfo MyWorkerInfo = NULL; /* PID of launcher, valid only in worker while shutting down */ int AutovacuumLauncherPid = 0; -#ifdef EXEC_BACKEND -static pid_t avlauncher_forkexec(void); -static pid_t avworker_forkexec(void); -#endif NON_EXEC_STATIC void AutoVacWorkerMain(int argc, char *argv[]) pg_attribute_noreturn(); NON_EXEC_STATIC void AutoVacLauncherMain(int argc, char *argv[]) pg_attribute_noreturn(); @@ -347,88 +343,53 @@ static void avl_sigusr2_handler(SIGNAL_ARGS); static void avl_sigterm_handler(SIGNAL_ARGS); static void autovac_refresh_stats(void); - - /******************************************************************** * AUTOVACUUM LAUNCHER CODE ********************************************************************/ -#ifdef EXEC_BACKEND /* - * forkexec routine for the autovacuum launcher process. + * PrepAutoVacProcessFork * * Format up the arglist, then fork and exec. */ -static pid_t -avlauncher_forkexec(void) +void +PrepAutoVacProcessFork(ForkProcData *autovac_fork) { - char *av[10]; int ac = 0; - av[ac++] = "postgres"; - av[ac++] = "--forkavlauncher"; - av[ac++] = NULL; /* filled in by postmaster_forkexec */ - av[ac] = NULL; - - Assert(ac < lengthof(av)); - - return postmaster_forkexec(ac, av); -} - /* - * We need this set from the outside, before InitProcess is called + * Set up command-line arguments for subprocess */ -void -AutovacuumLauncherIAm(void) -{ - am_autovacuum_launcher = true; -} -#endif + autovac_fork->av[ac++] = pstrdup("postgres"); -/* - * Main entry point for autovacuum launcher process, to be called from the - * postmaster. - */ -int -StartAutoVacLauncher(void) + if (MyForkProcType == AutoVacLauncherFork) { - pid_t AutoVacPID; - + autovac_fork->type_desc = pstrdup("autovacuum launcher"); + autovac_fork->child_main = AutoVacLauncherMain; #ifdef EXEC_BACKEND - switch ((AutoVacPID = avlauncher_forkexec())) -#else - switch ((AutoVacPID = fork_process())) + autovac_fork->av[ac++] = pstrdup("--forkavlauncher"); + autovac_fork->av[ac++] = NULL; /* filled in by postmaster_forkexec */ #endif + } + else if (MyForkProcType == AutoVacWorkerFork) { - case -1: - ereport(LOG, - (errmsg("could not fork autovacuum launcher process: %m"))); - return 0; - -#ifndef EXEC_BACKEND - case 0: - /* in postmaster child ... */ - InitPostmasterChild(); - - /* Close the postmaster's sockets */ - ClosePostmasterPorts(false); - - AutoVacLauncherMain(0, NULL); - break; + autovac_fork->type_desc = pstrdup("autovacuum worker"); + autovac_fork->child_main = AutoVacWorkerMain; +#ifdef EXEC_BACKEND + autovac_fork->av[ac++] = pstrdup("--forkavworker"); + autovac_fork->av[ac++] = NULL; /* filled in by postmaster_forkexec */ #endif - default: - return (int) AutoVacPID; } - /* shouldn't get here */ - return 0; + autovac_fork->ac = ac; + Assert(autovac_fork->ac < lengthof(*autovac_fork->av)); } /* * Main loop for the autovacuum launcher process. */ NON_EXEC_STATIC void -AutoVacLauncherMain(int argc, char *argv[]) +AutoVacLauncherMain(pg_attribute_unused() int argc, pg_attribute_unused() char *argv[]) { sigjmp_buf local_sigjmp_buf; @@ -1428,83 +1389,11 @@ avl_sigterm_handler(SIGNAL_ARGS) * AUTOVACUUM WORKER CODE ********************************************************************/ -#ifdef EXEC_BACKEND -/* - * forkexec routines for the autovacuum worker. - * - * Format up the arglist, then fork and exec. - */ -static pid_t -avworker_forkexec(void) -{ - char *av[10]; - int ac = 0; - - av[ac++] = "postgres"; - av[ac++] = "--forkavworker"; - av[ac++] = NULL; /* filled in by postmaster_forkexec */ - av[ac] = NULL; - - Assert(ac < lengthof(av)); - - return postmaster_forkexec(ac, av); -} - -/* - * We need this set from the outside, before InitProcess is called - */ -void -AutovacuumWorkerIAm(void) -{ - am_autovacuum_worker = true; -} -#endif - -/* - * Main entry point for autovacuum worker process. - * - * This code is heavily based on pgarch.c, q.v. - */ -int -StartAutoVacWorker(void) -{ - pid_t worker_pid; - -#ifdef EXEC_BACKEND - switch ((worker_pid = avworker_forkexec())) -#else - switch ((worker_pid = fork_process())) -#endif - { - case -1: - ereport(LOG, - (errmsg("could not fork autovacuum worker process: %m"))); - return 0; - -#ifndef EXEC_BACKEND - case 0: - /* in postmaster child ... */ - InitPostmasterChild(); - - /* Close the postmaster's sockets */ - ClosePostmasterPorts(false); - - AutoVacWorkerMain(0, NULL); - break; -#endif - default: - return (int) worker_pid; - } - - /* shouldn't get here */ - return 0; -} - /* * AutoVacWorkerMain */ NON_EXEC_STATIC void -AutoVacWorkerMain(int argc, char *argv[]) +AutoVacWorkerMain(pg_attribute_unused() int argc, pg_attribute_unused() char *argv[]) { sigjmp_buf local_sigjmp_buf; Oid dbid; diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index e0d11cc6ab..35cd1479b9 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -414,6 +414,9 @@ static bool RandomCancelKey(int32 *cancel_key); static void signal_child(pid_t pid, int signal); static bool SignalSomeChildren(int signal, int targets); static void TerminateChildren(int signal); +#ifdef EXEC_BACKEND +static void shmemSetup(bool aux_process); +#endif #define SignalChildren(sig) SignalSomeChildren(sig, BACKEND_TYPE_ALL) @@ -544,6 +547,8 @@ static void ShmemBackendArrayRemove(Backend *bn); #define StartCheckpointer() StartChildProcess(CheckpointerFork) #define StartWalWriter() StartChildProcess(WalWriterFork) #define StartWalReceiver() StartChildProcess(WalReceiverFork) +#define StartAutoVacLauncher() StartChildProcess(AutoVacLauncherFork) +#define StartAutoVacWorker() StartChildProcess(AutoVacWorkerFork) /* Macros to check exit status of a child process */ #define EXIT_STATUS_0(st) ((st) == 0) @@ -4858,6 +4863,29 @@ retry: } #endif /* WIN32 */ +/* + * shmemSetup + * + * Helper function for a child to set up shmem before + * executing. + * + * aux_process - set to true if an auxiliary process. + */ +static void +shmemSetup(bool aux_process) +{ + /* Restore basic shared memory pointers */ + InitShmemAccess(UsedShmemSegAddr); + + /* Need a PGPROC to run CreateSharedMemoryAndSemaphores */ + if (aux_process) + InitAuxiliaryProcess(); + else + InitProcess(); + + /* Attach process to shared data structures */ + CreateSharedMemoryAndSemaphores(); +} /* * SubPostmasterMain -- Get the fork/exec'd process into a state equivalent @@ -4943,9 +4971,9 @@ SubPostmasterMain(int argc, char *argv[]) /* autovacuum needs this set before calling InitProcess */ if (strcmp(argv[1], "--forkavlauncher") == 0) - AutovacuumLauncherIAm(); + am_autovacuum_launcher = true; if (strcmp(argv[1], "--forkavworker") == 0) - AutovacuumWorkerIAm(); + am_autovacuum_worker = true; /* * Start our win32 signal implementation. This has to be done after we @@ -5038,41 +5066,17 @@ SubPostmasterMain(int argc, char *argv[]) } if (strcmp(argv[1], "--forkboot") == 0) { - /* Restore basic shared memory pointers */ - InitShmemAccess(UsedShmemSegAddr); - - /* Need a PGPROC to run CreateSharedMemoryAndSemaphores */ - InitAuxiliaryProcess(); - - /* Attach process to shared data structures */ - CreateSharedMemoryAndSemaphores(); - + shmemSetup(true); AuxiliaryProcessMain(argc - 2, argv + 2); /* does not return */ } if (strcmp(argv[1], "--forkavlauncher") == 0) { - /* Restore basic shared memory pointers */ - InitShmemAccess(UsedShmemSegAddr); - - /* Need a PGPROC to run CreateSharedMemoryAndSemaphores */ - InitProcess(); - - /* Attach process to shared data structures */ - CreateSharedMemoryAndSemaphores(); - + shmemSetup(true); AutoVacLauncherMain(argc - 2, argv + 2); /* does not return */ } if (strcmp(argv[1], "--forkavworker") == 0) { - /* Restore basic shared memory pointers */ - InitShmemAccess(UsedShmemSegAddr); - - /* Need a PGPROC to run CreateSharedMemoryAndSemaphores */ - InitProcess(); - - /* Attach process to shared data structures */ - CreateSharedMemoryAndSemaphores(); - + shmemSetup(true); AutoVacWorkerMain(argc - 2, argv + 2); /* does not return */ } if (strncmp(argv[1], "--forkbgworker=", 15) == 0) @@ -5450,6 +5454,11 @@ StartChildProcess(ForkProcType type) case WalReceiverFork: PrepAuxProcessFork(fork_data); break; + /* Non-Auxiliary Processes */ + case AutoVacLauncherFork: + case AutoVacWorkerFork: + PrepAutoVacProcessFork(fork_data); + break; default: break; diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h index 8451e5d9e2..518775f528 100644 --- a/src/include/postmaster/autovacuum.h +++ b/src/include/postmaster/autovacuum.h @@ -15,6 +15,7 @@ #define AUTOVACUUM_H #include "storage/block.h" +#include "postmaster/fork_process.h" /* * Other processes can request specific work from autovacuum, identified by @@ -45,6 +46,10 @@ extern int AutovacuumLauncherPid; extern int Log_autovacuum_min_duration; +/* autovacuum identification */ +extern bool am_autovacuum_launcher; +extern bool am_autovacuum_worker; + /* Status inquiry functions */ extern bool AutoVacuumingActive(void); extern bool IsAutoVacuumLauncherProcess(void); @@ -58,6 +63,8 @@ extern void autovac_init(void); extern int StartAutoVacLauncher(void); extern int StartAutoVacWorker(void); +extern void PrepAutoVacProcessFork(ForkProcData *autovac_fork); + /* called from postmaster when a worker could not be forked */ extern void AutoVacWorkerFailed(void); @@ -67,8 +74,6 @@ extern void AutoVacuumUpdateDelay(void); #ifdef EXEC_BACKEND extern void AutoVacLauncherMain(int argc, char *argv[]) pg_attribute_noreturn(); extern void AutoVacWorkerMain(int argc, char *argv[]) pg_attribute_noreturn(); -extern void AutovacuumWorkerIAm(void); -extern void AutovacuumLauncherIAm(void); #endif extern bool AutoVacuumRequestWork(AutoVacuumWorkItemType type, diff --git a/src/include/postmaster/fork_process.h b/src/include/postmaster/fork_process.h index d912229055..1f319fc98f 100644 --- a/src/include/postmaster/fork_process.h +++ b/src/include/postmaster/fork_process.h @@ -24,6 +24,8 @@ typedef enum CheckpointerFork, WalWriterFork, WalReceiverFork, /* end of Auxiliary Process Forks */ + AutoVacLauncherFork, + AutoVacWorkerFork, NUMFORKPROCTYPES /* Must be last! */ } ForkProcType; -- 2.23.0