1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

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

@@ -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);