Commit 164adc4d authored by Neil Conway's avatar Neil Conway

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.
parent e829f822
...@@ -265,7 +265,7 @@ beos_startup(int argc, char **argv) ...@@ -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. 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 We need to do a remapping of these areas. Just afer the fork we performe the
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Makefile for src/backend/postmaster # Makefile for src/backend/postmaster
# #
# IDENTIFICATION # 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 ...@@ -12,7 +12,7 @@ subdir = src/backend/postmaster
top_builddir = ../../.. top_builddir = ../../..
include $(top_builddir)/src/Makefile.global 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 all: SUBSYS.o
......
/*
* 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;
}
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -34,6 +34,7 @@
#include "access/xlog_internal.h" #include "access/xlog_internal.h"
#include "libpq/pqsignal.h" #include "libpq/pqsignal.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "postmaster/fork_process.h"
#include "postmaster/pgarch.h" #include "postmaster/pgarch.h"
#include "postmaster/postmaster.h" #include "postmaster/postmaster.h"
#include "storage/fd.h" #include "storage/fd.h"
...@@ -141,25 +142,13 @@ pgarch_start(void) ...@@ -141,25 +142,13 @@ pgarch_start(void)
return 0; return 0;
last_pgarch_start_time = curtime; 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 #ifdef EXEC_BACKEND
switch ((pgArchPid = pgarch_forkexec())) switch ((pgArchPid = pgarch_forkexec()))
#else #else
switch ((pgArchPid = fork())) switch ((pgArchPid = fork_process()))
#endif #endif
{ {
case -1: case -1:
#ifdef __BEOS__
/* Specific beos actions */
beos_backend_startup_failed();
#endif
ereport(LOG, ereport(LOG,
(errmsg("could not fork archiver: %m"))); (errmsg("could not fork archiver: %m")));
return 0; return 0;
...@@ -167,10 +156,6 @@ pgarch_start(void) ...@@ -167,10 +156,6 @@ pgarch_start(void)
#ifndef EXEC_BACKEND #ifndef EXEC_BACKEND
case 0: case 0:
/* in postmaster child ... */ /* in postmaster child ... */
#ifdef __BEOS__
/* Specific beos actions after backend startup */
beos_backend_startup();
#endif
/* Close the postmaster's sockets */ /* Close the postmaster's sockets */
ClosePostmasterPorts(false); ClosePostmasterPorts(false);
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* *
...@@ -92,6 +92,8 @@ ...@@ -92,6 +92,8 @@
#include <DNSServiceDiscovery/DNSServiceDiscovery.h> #include <DNSServiceDiscovery/DNSServiceDiscovery.h>
#endif #endif
#include "access/xlog.h"
#include "bootstrap/bootstrap.h"
#include "catalog/pg_control.h" #include "catalog/pg_control.h"
#include "catalog/pg_database.h" #include "catalog/pg_database.h"
#include "commands/async.h" #include "commands/async.h"
...@@ -103,23 +105,22 @@ ...@@ -103,23 +105,22 @@
#include "libpq/pqsignal.h" #include "libpq/pqsignal.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "nodes/nodes.h" #include "nodes/nodes.h"
#include "postmaster/postmaster.h" #include "pgstat.h"
#include "postmaster/fork_process.h"
#include "postmaster/pgarch.h" #include "postmaster/pgarch.h"
#include "postmaster/postmaster.h"
#include "postmaster/syslogger.h" #include "postmaster/syslogger.h"
#include "storage/bufmgr.h"
#include "storage/fd.h" #include "storage/fd.h"
#include "storage/ipc.h" #include "storage/ipc.h"
#include "storage/pg_shmem.h" #include "storage/pg_shmem.h"
#include "storage/pmsignal.h" #include "storage/pmsignal.h"
#include "storage/proc.h" #include "storage/proc.h"
#include "storage/bufmgr.h"
#include "access/xlog.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/guc.h" #include "utils/guc.h"
#include "utils/memutils.h" #include "utils/memutils.h"
#include "utils/ps_status.h" #include "utils/ps_status.h"
#include "bootstrap/bootstrap.h"
#include "pgstat.h"
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
#include "storage/spin.h" #include "storage/spin.h"
...@@ -1008,16 +1009,7 @@ pmdaemonize(void) ...@@ -1008,16 +1009,7 @@ pmdaemonize(void)
int i; int i;
pid_t pid; pid_t pid;
#ifdef LINUX_PROFILE pid = fork_process();
struct itimerval prof_itimer;
#endif
#ifdef LINUX_PROFILE
/* see comments in BackendStartup */
getitimer(ITIMER_PROF, &prof_itimer);
#endif
pid = fork();
if (pid == (pid_t) -1) if (pid == (pid_t) -1)
{ {
write_stderr("%s: could not fork background process: %s\n", write_stderr("%s: could not fork background process: %s\n",
...@@ -1030,10 +1022,6 @@ pmdaemonize(void) ...@@ -1030,10 +1022,6 @@ pmdaemonize(void)
_exit(0); _exit(0);
} }
#ifdef LINUX_PROFILE
setitimer(ITIMER_PROF, &prof_itimer, NULL);
#endif
MyProcPid = PostmasterPid = getpid(); /* reset PID vars to child */ MyProcPid = PostmasterPid = getpid(); /* reset PID vars to child */
/* GH: If there's no setsid(), we hopefully don't need silent mode. /* GH: If there's no setsid(), we hopefully don't need silent mode.
...@@ -2382,10 +2370,6 @@ BackendStartup(Port *port) ...@@ -2382,10 +2370,6 @@ BackendStartup(Port *port)
Backend *bn; /* for backend cleanup */ Backend *bn; /* for backend cleanup */
pid_t pid; pid_t pid;
#ifdef LINUX_PROFILE
struct itimerval prof_itimer;
#endif
/* /*
* Compute the cancel key that will be assigned to this backend. The * 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 * backend will have its own copy in the forked-off process' value of
...@@ -2409,54 +2393,13 @@ BackendStartup(Port *port) ...@@ -2409,54 +2393,13 @@ BackendStartup(Port *port)
/* Pass down canAcceptConnections state (kluge for EXEC_BACKEND case) */ /* Pass down canAcceptConnections state (kluge for EXEC_BACKEND case) */
port->canAcceptConnections = canAcceptConnections(); 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 #ifdef EXEC_BACKEND
pid = backend_forkexec(port); pid = backend_forkexec(port);
#else /* !EXEC_BACKEND */ #else /* !EXEC_BACKEND */
pid = fork_process();
#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();
if (pid == 0) /* child */ 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); free(bn);
proc_exit(BackendRun(port)); proc_exit(BackendRun(port));
} }
#endif /* EXEC_BACKEND */ #endif /* EXEC_BACKEND */
...@@ -2466,10 +2409,6 @@ BackendStartup(Port *port) ...@@ -2466,10 +2409,6 @@ BackendStartup(Port *port)
/* in parent, fork failed */ /* in parent, fork failed */
int save_errno = errno; int save_errno = errno;
#ifdef __BEOS__
/* Specific beos backend startup actions */
beos_backend_startup_failed();
#endif
free(bn); free(bn);
errno = save_errno; errno = save_errno;
ereport(LOG, ereport(LOG,
...@@ -2945,7 +2884,7 @@ internal_forkexec(int argc, char *argv[], Port *port) ...@@ -2945,7 +2884,7 @@ internal_forkexec(int argc, char *argv[], Port *port)
argv[2] = tmpfilename; argv[2] = tmpfilename;
/* Fire off execv in child */ /* Fire off execv in child */
if ((pid = fork()) == 0) if ((pid = fork_process()) == 0)
{ {
if (execv(postgres_exec_path, argv) < 0) if (execv(postgres_exec_path, argv) < 0)
{ {
...@@ -3465,10 +3404,6 @@ StartChildProcess(int xlop) ...@@ -3465,10 +3404,6 @@ StartChildProcess(int xlop)
int ac = 0; int ac = 0;
char xlbuf[32]; char xlbuf[32];
#ifdef LINUX_PROFILE
struct itimerval prof_itimer;
#endif
/* /*
* Set up command-line arguments for subprocess * Set up command-line arguments for subprocess
*/ */
...@@ -3488,41 +3423,13 @@ StartChildProcess(int xlop) ...@@ -3488,41 +3423,13 @@ StartChildProcess(int xlop)
av[ac] = NULL; av[ac] = NULL;
Assert(ac < lengthof(av)); Assert(ac < lengthof(av));
/*
* Flush stdio channels (see comments in BackendStartup)
*/
fflush(stdout);
fflush(stderr);
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
pid = postmaster_forkexec(ac, av); pid = postmaster_forkexec(ac, av);
#else /* !EXEC_BACKEND */ #else /* !EXEC_BACKEND */
pid = fork_process();
#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();
if (pid == 0) /* child */ 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 IsUnderPostmaster = true; /* we are a postmaster subprocess
* now */ * now */
...@@ -3546,11 +3453,6 @@ StartChildProcess(int xlop) ...@@ -3546,11 +3453,6 @@ StartChildProcess(int xlop)
{ {
/* in parent, fork failed */ /* in parent, fork failed */
int save_errno = errno; int save_errno = errno;
#ifdef __BEOS__
/* Specific beos actions before backend startup */
beos_backend_startup_failed();
#endif
errno = save_errno; errno = save_errno;
switch (xlop) switch (xlop)
{ {
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -33,6 +33,7 @@
#include "libpq/pqsignal.h" #include "libpq/pqsignal.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "postmaster/fork_process.h"
#include "postmaster/postmaster.h" #include "postmaster/postmaster.h"
#include "postmaster/syslogger.h" #include "postmaster/syslogger.h"
#include "pgtime.h" #include "pgtime.h"
...@@ -451,28 +452,13 @@ SysLogger_Start(void) ...@@ -451,28 +452,13 @@ SysLogger_Start(void)
pfree(filename); 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 #ifdef EXEC_BACKEND
switch ((sysloggerPid = syslogger_forkexec())) switch ((sysloggerPid = syslogger_forkexec()))
#else #else
switch ((sysloggerPid = fork())) switch ((sysloggerPid = fork_process()))
#endif #endif
{ {
case -1: case -1:
#ifdef __BEOS__
/* Specific beos actions */
beos_backend_startup_failed();
#endif
ereport(LOG, ereport(LOG,
(errmsg("could not fork system logger: %m"))); (errmsg("could not fork system logger: %m")));
return 0; return 0;
...@@ -480,10 +466,6 @@ SysLogger_Start(void) ...@@ -480,10 +466,6 @@ SysLogger_Start(void)
#ifndef EXEC_BACKEND #ifndef EXEC_BACKEND
case 0: case 0:
/* in postmaster child ... */ /* in postmaster child ... */
#ifdef __BEOS__
/* Specific beos actions after backend startup */
beos_backend_startup();
#endif
/* Close the postmaster's sockets */ /* Close the postmaster's sockets */
ClosePostmasterPorts(true); ClosePostmasterPorts(true);
......
#ifndef FORK_PROCESS_H
#define FORK_PROCESS_H
#include "postgres.h"
extern pid_t fork_process(void);
#endif /* ! FORK_PROCESS_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment