Skip to content

Commit aafc05d

Browse files
committed
Refactor postmaster child process launching
Introduce new postmaster_child_launch() function that deals with the differences in EXEC_BACKEND mode. Refactor the mechanism of passing information from the parent to child process. Instead of using different command-line arguments when launching the child process in EXEC_BACKEND mode, pass a variable-length blob of startup data along with all the global variables. The contents of that blob depend on the kind of child process being launched. In !EXEC_BACKEND mode, we use the same blob, but it's simply inherited from the parent to child process. Reviewed-by: Tristan Partin, Andres Freund Discussion: https://www.postgresql.org/message-id/7a59b073-5b5b-151e-7ed3-8b01ff7ce9ef@iki.fi
1 parent f1baed1 commit aafc05d

28 files changed

+656
-988
lines changed

src/backend/postmaster/autovacuum.c

+19-134
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@
8585
#include "nodes/makefuncs.h"
8686
#include "pgstat.h"
8787
#include "postmaster/autovacuum.h"
88-
#include "postmaster/fork_process.h"
8988
#include "postmaster/interrupt.h"
9089
#include "postmaster/postmaster.h"
9190
#include "storage/bufmgr.h"
@@ -311,13 +310,6 @@ static WorkerInfo MyWorkerInfo = NULL;
311310
/* PID of launcher, valid only in worker while shutting down */
312311
int AutovacuumLauncherPid = 0;
313312

314-
#ifdef EXEC_BACKEND
315-
static pid_t avlauncher_forkexec(void);
316-
static pid_t avworker_forkexec(void);
317-
#endif
318-
NON_EXEC_STATIC void AutoVacWorkerMain(int argc, char *argv[]) pg_attribute_noreturn();
319-
NON_EXEC_STATIC void AutoVacLauncherMain(int argc, char *argv[]) pg_attribute_noreturn();
320-
321313
static Oid do_start_worker(void);
322314
static void HandleAutoVacLauncherInterrupts(void);
323315
static void AutoVacLauncherShutdown(void) pg_attribute_noreturn();
@@ -361,76 +353,23 @@ static void avl_sigusr2_handler(SIGNAL_ARGS);
361353
* AUTOVACUUM LAUNCHER CODE
362354
********************************************************************/
363355

364-
#ifdef EXEC_BACKEND
365356
/*
366-
* forkexec routine for the autovacuum launcher process.
367-
*
368-
* Format up the arglist, then fork and exec.
357+
* Main entry point for the autovacuum launcher process.
369358
*/
370-
static pid_t
371-
avlauncher_forkexec(void)
359+
void
360+
AutoVacLauncherMain(char *startup_data, size_t startup_data_len)
372361
{
373-
char *av[10];
374-
int ac = 0;
375-
376-
av[ac++] = "postgres";
377-
av[ac++] = "--forkavlauncher";
378-
av[ac++] = NULL; /* filled in by postmaster_forkexec */
379-
av[ac] = NULL;
380-
381-
Assert(ac < lengthof(av));
382-
383-
return postmaster_forkexec(ac, av);
384-
}
385-
#endif
362+
sigjmp_buf local_sigjmp_buf;
386363

387-
/*
388-
* Main entry point for autovacuum launcher process, to be called from the
389-
* postmaster.
390-
*/
391-
int
392-
StartAutoVacLauncher(void)
393-
{
394-
pid_t AutoVacPID;
364+
Assert(startup_data_len == 0);
395365

396-
#ifdef EXEC_BACKEND
397-
switch ((AutoVacPID = avlauncher_forkexec()))
398-
#else
399-
switch ((AutoVacPID = fork_process()))
400-
#endif
366+
/* Release postmaster's working memory context */
367+
if (PostmasterContext)
401368
{
402-
case -1:
403-
ereport(LOG,
404-
(errmsg("could not fork autovacuum launcher process: %m")));
405-
return 0;
406-
407-
#ifndef EXEC_BACKEND
408-
case 0:
409-
/* in postmaster child ... */
410-
InitPostmasterChild();
411-
412-
/* Close the postmaster's sockets */
413-
ClosePostmasterPorts(false);
414-
415-
AutoVacLauncherMain(0, NULL);
416-
break;
417-
#endif
418-
default:
419-
return (int) AutoVacPID;
369+
MemoryContextDelete(PostmasterContext);
370+
PostmasterContext = NULL;
420371
}
421372

422-
/* shouldn't get here */
423-
return 0;
424-
}
425-
426-
/*
427-
* Main loop for the autovacuum launcher process.
428-
*/
429-
NON_EXEC_STATIC void
430-
AutoVacLauncherMain(int argc, char *argv[])
431-
{
432-
sigjmp_buf local_sigjmp_buf;
433-
434373
MyBackendType = B_AUTOVAC_LAUNCHER;
435374
init_ps_display(NULL);
436375

@@ -1412,78 +1351,24 @@ avl_sigusr2_handler(SIGNAL_ARGS)
14121351
* AUTOVACUUM WORKER CODE
14131352
********************************************************************/
14141353

1415-
#ifdef EXEC_BACKEND
14161354
/*
1417-
* forkexec routines for the autovacuum worker.
1418-
*
1419-
* Format up the arglist, then fork and exec.
1355+
* Main entry point for autovacuum worker processes.
14201356
*/
1421-
static pid_t
1422-
avworker_forkexec(void)
1357+
void
1358+
AutoVacWorkerMain(char *startup_data, size_t startup_data_len)
14231359
{
1424-
char *av[10];
1425-
int ac = 0;
1426-
1427-
av[ac++] = "postgres";
1428-
av[ac++] = "--forkavworker";
1429-
av[ac++] = NULL; /* filled in by postmaster_forkexec */
1430-
av[ac] = NULL;
1431-
1432-
Assert(ac < lengthof(av));
1433-
1434-
return postmaster_forkexec(ac, av);
1435-
}
1436-
#endif
1360+
sigjmp_buf local_sigjmp_buf;
1361+
Oid dbid;
14371362

1438-
/*
1439-
* Main entry point for autovacuum worker process.
1440-
*
1441-
* This code is heavily based on pgarch.c, q.v.
1442-
*/
1443-
int
1444-
StartAutoVacWorker(void)
1445-
{
1446-
pid_t worker_pid;
1363+
Assert(startup_data_len == 0);
14471364

1448-
#ifdef EXEC_BACKEND
1449-
switch ((worker_pid = avworker_forkexec()))
1450-
#else
1451-
switch ((worker_pid = fork_process()))
1452-
#endif
1365+
/* Release postmaster's working memory context */
1366+
if (PostmasterContext)
14531367
{
1454-
case -1:
1455-
ereport(LOG,
1456-
(errmsg("could not fork autovacuum worker process: %m")));
1457-
return 0;
1458-
1459-
#ifndef EXEC_BACKEND
1460-
case 0:
1461-
/* in postmaster child ... */
1462-
InitPostmasterChild();
1463-
1464-
/* Close the postmaster's sockets */
1465-
ClosePostmasterPorts(false);
1466-
1467-
AutoVacWorkerMain(0, NULL);
1468-
break;
1469-
#endif
1470-
default:
1471-
return (int) worker_pid;
1368+
MemoryContextDelete(PostmasterContext);
1369+
PostmasterContext = NULL;
14721370
}
14731371

1474-
/* shouldn't get here */
1475-
return 0;
1476-
}
1477-
1478-
/*
1479-
* AutoVacWorkerMain
1480-
*/
1481-
NON_EXEC_STATIC void
1482-
AutoVacWorkerMain(int argc, char *argv[])
1483-
{
1484-
sigjmp_buf local_sigjmp_buf;
1485-
Oid dbid;
1486-
14871372
MyBackendType = B_AUTOVAC_WORKER;
14881373
init_ps_display(NULL);
14891374

src/backend/postmaster/auxprocess.c

+11-42
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,30 @@
2727
#include "storage/ipc.h"
2828
#include "storage/proc.h"
2929
#include "storage/procsignal.h"
30+
#include "utils/memutils.h"
3031
#include "utils/ps_status.h"
3132

3233

3334
static void ShutdownAuxiliaryProcess(int code, Datum arg);
3435

3536

3637
/*
37-
* AuxiliaryProcessMain
38+
* AuxiliaryProcessMainCommon
3839
*
39-
* The main entry point for auxiliary processes, such as the bgwriter,
40-
* walwriter, walreceiver, bootstrapper and the shared memory checker code.
41-
*
42-
* This code is here just because of historical reasons.
40+
* Common initialization code for auxiliary processes, such as the bgwriter,
41+
* walwriter, walreceiver, and the startup process.
4342
*/
4443
void
45-
AuxiliaryProcessMain(BackendType auxtype)
44+
AuxiliaryProcessMainCommon(void)
4645
{
4746
Assert(IsUnderPostmaster);
4847

49-
MyBackendType = auxtype;
48+
/* Release postmaster's working memory context */
49+
if (PostmasterContext)
50+
{
51+
MemoryContextDelete(PostmasterContext);
52+
PostmasterContext = NULL;
53+
}
5054

5155
init_ps_display(NULL);
5256

@@ -84,41 +88,6 @@ AuxiliaryProcessMain(BackendType auxtype)
8488
before_shmem_exit(ShutdownAuxiliaryProcess, 0);
8589

8690
SetProcessingMode(NormalProcessing);
87-
88-
switch (MyBackendType)
89-
{
90-
case B_STARTUP:
91-
StartupProcessMain();
92-
proc_exit(1);
93-
94-
case B_ARCHIVER:
95-
PgArchiverMain();
96-
proc_exit(1);
97-
98-
case B_BG_WRITER:
99-
BackgroundWriterMain();
100-
proc_exit(1);
101-
102-
case B_CHECKPOINTER:
103-
CheckpointerMain();
104-
proc_exit(1);
105-
106-
case B_WAL_WRITER:
107-
WalWriterMain();
108-
proc_exit(1);
109-
110-
case B_WAL_RECEIVER:
111-
WalReceiverMain();
112-
proc_exit(1);
113-
114-
case B_WAL_SUMMARIZER:
115-
WalSummarizerMain();
116-
proc_exit(1);
117-
118-
default:
119-
elog(PANIC, "unrecognized process type: %d", (int) MyBackendType);
120-
proc_exit(1);
121-
}
12291
}
12392

12493
/*

src/backend/postmaster/bgworker.c

+17-3
Original file line numberDiff line numberDiff line change
@@ -720,15 +720,29 @@ bgworker_die(SIGNAL_ARGS)
720720
* Main entry point for background worker processes.
721721
*/
722722
void
723-
BackgroundWorkerMain(void)
723+
BackgroundWorkerMain(char *startup_data, size_t startup_data_len)
724724
{
725725
sigjmp_buf local_sigjmp_buf;
726-
BackgroundWorker *worker = MyBgworkerEntry;
726+
BackgroundWorker *worker;
727727
bgworker_main_type entrypt;
728728

729-
if (worker == NULL)
729+
if (startup_data == NULL)
730730
elog(FATAL, "unable to find bgworker entry");
731+
Assert(startup_data_len == sizeof(BackgroundWorker));
732+
worker = MemoryContextAlloc(TopMemoryContext, sizeof(BackgroundWorker));
733+
memcpy(worker, startup_data, sizeof(BackgroundWorker));
731734

735+
/*
736+
* Now that we're done reading the startup data, release postmaster's
737+
* working memory context.
738+
*/
739+
if (PostmasterContext)
740+
{
741+
MemoryContextDelete(PostmasterContext);
742+
PostmasterContext = NULL;
743+
}
744+
745+
MyBgworkerEntry = worker;
732746
MyBackendType = B_BG_WORKER;
733747
init_ps_display(worker->bgw_name);
734748

src/backend/postmaster/bgwriter.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "libpq/pqsignal.h"
3636
#include "miscadmin.h"
3737
#include "pgstat.h"
38+
#include "postmaster/auxprocess.h"
3839
#include "postmaster/bgwriter.h"
3940
#include "postmaster/interrupt.h"
4041
#include "storage/buf_internals.h"
@@ -83,13 +84,18 @@ static XLogRecPtr last_snapshot_lsn = InvalidXLogRecPtr;
8384
* basic execution environment, but not enabled signals yet.
8485
*/
8586
void
86-
BackgroundWriterMain(void)
87+
BackgroundWriterMain(char *startup_data, size_t startup_data_len)
8788
{
8889
sigjmp_buf local_sigjmp_buf;
8990
MemoryContext bgwriter_context;
9091
bool prev_hibernate;
9192
WritebackContext wb_context;
9293

94+
Assert(startup_data_len == 0);
95+
96+
MyBackendType = B_BG_WRITER;
97+
AuxiliaryProcessMainCommon();
98+
9399
/*
94100
* Properly accept or ignore signals that might be sent to us.
95101
*/

src/backend/postmaster/checkpointer.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "libpq/pqsignal.h"
4343
#include "miscadmin.h"
4444
#include "pgstat.h"
45+
#include "postmaster/auxprocess.h"
4546
#include "postmaster/bgwriter.h"
4647
#include "postmaster/interrupt.h"
4748
#include "replication/syncrep.h"
@@ -169,11 +170,16 @@ static void ReqCheckpointHandler(SIGNAL_ARGS);
169170
* basic execution environment, but not enabled signals yet.
170171
*/
171172
void
172-
CheckpointerMain(void)
173+
CheckpointerMain(char *startup_data, size_t startup_data_len)
173174
{
174175
sigjmp_buf local_sigjmp_buf;
175176
MemoryContext checkpointer_context;
176177

178+
Assert(startup_data_len == 0);
179+
180+
MyBackendType = B_CHECKPOINTER;
181+
AuxiliaryProcessMainCommon();
182+
177183
CheckpointerShmem->checkpointer_pid = MyProcPid;
178184

179185
/*

0 commit comments

Comments
 (0)