Refactor fork()-related code. We need to do various housekeeping tasks

before we can invoke fork() -- flush stdio buffers, save and restore the
profiling timer on Linux with LINUX_PROFILE, and handle BeOS stuff. This
patch moves that code into a single function, fork_process(), instead of
duplicating it at the various callsites of fork().

This patch doesn't address the EXEC_BACKEND case; there is room for
further cleanup there.
This commit is contained in:
Neil Conway 2005-03-10 07:14:03 +00:00
parent e829f82223
commit 164adc4d39
7 changed files with 108 additions and 151 deletions

View File

@ -265,7 +265,7 @@ beos_startup(int argc, char **argv)
/* The behavior of fork is borken on beos regarding shared memory. In fact
/* The behavior of fork is broken on beos regarding shared memory. In fact
all shared memory areas are clones in copy on write mode in the new process.
We need to do a remapping of these areas. Just afer the fork we performe the

View File

@ -4,7 +4,7 @@
# Makefile for src/backend/postmaster
#
# IDENTIFICATION
# $PostgreSQL: pgsql/src/backend/postmaster/Makefile,v 1.19 2004/08/05 23:32:10 tgl Exp $
# $PostgreSQL: pgsql/src/backend/postmaster/Makefile,v 1.20 2005/03/10 07:14:03 neilc Exp $
#
#-------------------------------------------------------------------------
@ -12,7 +12,7 @@ subdir = src/backend/postmaster
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
OBJS = postmaster.o bgwriter.o pgstat.o pgarch.o syslogger.o
OBJS = bgwriter.o fork_process.o pgarch.o pgstat.o postmaster.o syslogger.o
all: SUBSYS.o

View File

@ -0,0 +1,80 @@
/*
* fork_process.c
* A simple wrapper on top of fork(). This does not handle the
* EXEC_BACKEND case; it might be extended to do so, but it would be
* considerably more complex.
*
* Copyright (c) 1996-2005, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/fork_process.c,v 1.1 2005/03/10 07:14:03 neilc Exp $
*/
#include "postgres.h"
#include "postmaster/fork_process.h"
#include <unistd.h>
/*
* Wrapper for fork(). Return values are the same as those for fork():
* -1 if the fork failed, 0 in the child process, and the PID of the
* child in the parent process.
*/
pid_t
fork_process(void)
{
pid_t result;
#ifdef LINUX_PROFILE
struct itimerval prof_itimer;
#endif
/*
* Flush stdio channels just before fork, to avoid double-output
* problems. Ideally we'd use fflush(NULL) here, but there are still a
* few non-ANSI stdio libraries out there (like SunOS 4.1.x) that
* coredump if we do. Presently stdout and stderr are the only stdio
* output channels used by the postmaster, so fflush'ing them should
* be sufficient.
*/
fflush(stdout);
fflush(stderr);
#ifdef LINUX_PROFILE
/*
* Linux's fork() resets the profiling timer in the child process. If
* we want to profile child processes then we need to save and restore
* the timer setting. This is a waste of time if not profiling,
* however, so only do it if commanded by specific -DLINUX_PROFILE
* switch.
*/
getitimer(ITIMER_PROF, &prof_itimer);
#endif
#ifdef __BEOS__
/* Specific beos actions before backend startup */
beos_before_backend_startup();
#endif
result = fork();
if (result == (pid_t) -1)
{
/* fork failed */
#ifdef __BEOS__
/* Specific beos backend startup actions */
beos_backend_startup_failed();
#endif
}
else if (result == 0)
{
/* fork succeeded, in child */
#ifdef LINUX_PROFILE
setitimer(ITIMER_PROF, &prof_itimer, NULL);
#endif
#ifdef __BEOS__
/* Specific beos backend startup actions */
beos_backend_startup();
#endif
}
return result;
}

View File

@ -19,7 +19,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.14 2004/12/31 22:00:40 pgsql Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/pgarch.c,v 1.15 2005/03/10 07:14:03 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@ -34,6 +34,7 @@
#include "access/xlog_internal.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "postmaster/fork_process.h"
#include "postmaster/pgarch.h"
#include "postmaster/postmaster.h"
#include "storage/fd.h"
@ -141,25 +142,13 @@ pgarch_start(void)
return 0;
last_pgarch_start_time = curtime;
fflush(stdout);
fflush(stderr);
#ifdef __BEOS__
/* Specific beos actions before backend startup */
beos_before_backend_startup();
#endif
#ifdef EXEC_BACKEND
switch ((pgArchPid = pgarch_forkexec()))
#else
switch ((pgArchPid = fork()))
switch ((pgArchPid = fork_process()))
#endif
{
case -1:
#ifdef __BEOS__
/* Specific beos actions */
beos_backend_startup_failed();
#endif
ereport(LOG,
(errmsg("could not fork archiver: %m")));
return 0;
@ -167,10 +156,6 @@ pgarch_start(void)
#ifndef EXEC_BACKEND
case 0:
/* in postmaster child ... */
#ifdef __BEOS__
/* Specific beos actions after backend startup */
beos_backend_startup();
#endif
/* Close the postmaster's sockets */
ClosePostmasterPorts(false);

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.445 2005/02/22 04:36:36 momjian Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.446 2005/03/10 07:14:03 neilc Exp $
*
* NOTES
*
@ -92,6 +92,8 @@
#include <DNSServiceDiscovery/DNSServiceDiscovery.h>
#endif
#include "access/xlog.h"
#include "bootstrap/bootstrap.h"
#include "catalog/pg_control.h"
#include "catalog/pg_database.h"
#include "commands/async.h"
@ -103,23 +105,22 @@
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "nodes/nodes.h"
#include "postmaster/postmaster.h"
#include "pgstat.h"
#include "postmaster/fork_process.h"
#include "postmaster/pgarch.h"
#include "postmaster/postmaster.h"
#include "postmaster/syslogger.h"
#include "storage/bufmgr.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/pg_shmem.h"
#include "storage/pmsignal.h"
#include "storage/proc.h"
#include "storage/bufmgr.h"
#include "access/xlog.h"
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "bootstrap/bootstrap.h"
#include "pgstat.h"
#ifdef EXEC_BACKEND
#include "storage/spin.h"
@ -1008,16 +1009,7 @@ pmdaemonize(void)
int i;
pid_t pid;
#ifdef LINUX_PROFILE
struct itimerval prof_itimer;
#endif
#ifdef LINUX_PROFILE
/* see comments in BackendStartup */
getitimer(ITIMER_PROF, &prof_itimer);
#endif
pid = fork();
pid = fork_process();
if (pid == (pid_t) -1)
{
write_stderr("%s: could not fork background process: %s\n",
@ -1030,10 +1022,6 @@ pmdaemonize(void)
_exit(0);
}
#ifdef LINUX_PROFILE
setitimer(ITIMER_PROF, &prof_itimer, NULL);
#endif
MyProcPid = PostmasterPid = getpid(); /* reset PID vars to child */
/* GH: If there's no setsid(), we hopefully don't need silent mode.
@ -2382,10 +2370,6 @@ BackendStartup(Port *port)
Backend *bn; /* for backend cleanup */
pid_t pid;
#ifdef LINUX_PROFILE
struct itimerval prof_itimer;
#endif
/*
* Compute the cancel key that will be assigned to this backend. The
* backend will have its own copy in the forked-off process' value of
@ -2409,54 +2393,13 @@ BackendStartup(Port *port)
/* Pass down canAcceptConnections state (kluge for EXEC_BACKEND case) */
port->canAcceptConnections = canAcceptConnections();
/*
* Flush stdio channels just before fork, to avoid double-output
* problems. Ideally we'd use fflush(NULL) here, but there are still a
* few non-ANSI stdio libraries out there (like SunOS 4.1.x) that
* coredump if we do. Presently stdout and stderr are the only stdio
* output channels used by the postmaster, so fflush'ing them should
* be sufficient.
*/
fflush(stdout);
fflush(stderr);
#ifdef EXEC_BACKEND
pid = backend_forkexec(port);
#else /* !EXEC_BACKEND */
#ifdef LINUX_PROFILE
/*
* Linux's fork() resets the profiling timer in the child process. If
* we want to profile child processes then we need to save and restore
* the timer setting. This is a waste of time if not profiling,
* however, so only do it if commanded by specific -DLINUX_PROFILE
* switch.
*/
getitimer(ITIMER_PROF, &prof_itimer);
#endif
#ifdef __BEOS__
/* Specific beos actions before backend startup */
beos_before_backend_startup();
#endif
pid = fork();
pid = fork_process();
if (pid == 0) /* child */
{
#ifdef LINUX_PROFILE
setitimer(ITIMER_PROF, &prof_itimer, NULL);
#endif
#ifdef __BEOS__
/* Specific beos backend startup actions */
beos_backend_startup();
#endif
free(bn);
proc_exit(BackendRun(port));
}
#endif /* EXEC_BACKEND */
@ -2466,10 +2409,6 @@ BackendStartup(Port *port)
/* in parent, fork failed */
int save_errno = errno;
#ifdef __BEOS__
/* Specific beos backend startup actions */
beos_backend_startup_failed();
#endif
free(bn);
errno = save_errno;
ereport(LOG,
@ -2945,7 +2884,7 @@ internal_forkexec(int argc, char *argv[], Port *port)
argv[2] = tmpfilename;
/* Fire off execv in child */
if ((pid = fork()) == 0)
if ((pid = fork_process()) == 0)
{
if (execv(postgres_exec_path, argv) < 0)
{
@ -3465,10 +3404,6 @@ StartChildProcess(int xlop)
int ac = 0;
char xlbuf[32];
#ifdef LINUX_PROFILE
struct itimerval prof_itimer;
#endif
/*
* Set up command-line arguments for subprocess
*/
@ -3488,41 +3423,13 @@ StartChildProcess(int xlop)
av[ac] = NULL;
Assert(ac < lengthof(av));
/*
* Flush stdio channels (see comments in BackendStartup)
*/
fflush(stdout);
fflush(stderr);
#ifdef EXEC_BACKEND
pid = postmaster_forkexec(ac, av);
#else /* !EXEC_BACKEND */
#ifdef LINUX_PROFILE
/* see comments in BackendStartup */
getitimer(ITIMER_PROF, &prof_itimer);
#endif
#ifdef __BEOS__
/* Specific beos actions before backend startup */
beos_before_backend_startup();
#endif
pid = fork();
pid = fork_process();
if (pid == 0) /* child */
{
#ifdef LINUX_PROFILE
setitimer(ITIMER_PROF, &prof_itimer, NULL);
#endif
#ifdef __BEOS__
/* Specific beos actions after backend startup */
beos_backend_startup();
#endif
IsUnderPostmaster = true; /* we are a postmaster subprocess
* now */
@ -3546,11 +3453,6 @@ StartChildProcess(int xlop)
{
/* in parent, fork failed */
int save_errno = errno;
#ifdef __BEOS__
/* Specific beos actions before backend startup */
beos_backend_startup_failed();
#endif
errno = save_errno;
switch (xlop)
{

View File

@ -18,7 +18,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.12 2005/01/01 20:44:16 tgl Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/syslogger.c,v 1.13 2005/03/10 07:14:03 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@ -33,6 +33,7 @@
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "postmaster/fork_process.h"
#include "postmaster/postmaster.h"
#include "postmaster/syslogger.h"
#include "pgtime.h"
@ -451,28 +452,13 @@ SysLogger_Start(void)
pfree(filename);
/*
* Now we can fork off the syslogger subprocess.
*/
fflush(stdout);
fflush(stderr);
#ifdef __BEOS__
/* Specific beos actions before backend startup */
beos_before_backend_startup();
#endif
#ifdef EXEC_BACKEND
switch ((sysloggerPid = syslogger_forkexec()))
#else
switch ((sysloggerPid = fork()))
switch ((sysloggerPid = fork_process()))
#endif
{
case -1:
#ifdef __BEOS__
/* Specific beos actions */
beos_backend_startup_failed();
#endif
ereport(LOG,
(errmsg("could not fork system logger: %m")));
return 0;
@ -480,10 +466,6 @@ SysLogger_Start(void)
#ifndef EXEC_BACKEND
case 0:
/* in postmaster child ... */
#ifdef __BEOS__
/* Specific beos actions after backend startup */
beos_backend_startup();
#endif
/* Close the postmaster's sockets */
ClosePostmasterPorts(true);

View File

@ -0,0 +1,8 @@
#ifndef FORK_PROCESS_H
#define FORK_PROCESS_H
#include "postgres.h"
extern pid_t fork_process(void);
#endif /* ! FORK_PROCESS_H */