From 164adc4d3924d5f0310dba24d4035313ca69245d Mon Sep 17 00:00:00 2001 From: Neil Conway Date: Thu, 10 Mar 2005 07:14:03 +0000 Subject: [PATCH] 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. --- src/backend/port/beos/support.c | 2 +- src/backend/postmaster/Makefile | 4 +- src/backend/postmaster/fork_process.c | 80 +++++++++++++++++ src/backend/postmaster/pgarch.c | 21 +---- src/backend/postmaster/postmaster.c | 120 +++----------------------- src/backend/postmaster/syslogger.c | 24 +----- src/include/postmaster/fork_process.h | 8 ++ 7 files changed, 108 insertions(+), 151 deletions(-) create mode 100644 src/backend/postmaster/fork_process.c create mode 100644 src/include/postmaster/fork_process.h diff --git a/src/backend/port/beos/support.c b/src/backend/port/beos/support.c index 2c0b3a9d49..3bfb6ae0d4 100644 --- a/src/backend/port/beos/support.c +++ b/src/backend/port/beos/support.c @@ -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 diff --git a/src/backend/postmaster/Makefile b/src/backend/postmaster/Makefile index fdb12febb4..054bb09060 100644 --- a/src/backend/postmaster/Makefile +++ b/src/backend/postmaster/Makefile @@ -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 diff --git a/src/backend/postmaster/fork_process.c b/src/backend/postmaster/fork_process.c new file mode 100644 index 0000000000..3098087db4 --- /dev/null +++ b/src/backend/postmaster/fork_process.c @@ -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 + +/* + * 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; +} diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c index 616e0a6327..fc2d9ce729 100644 --- a/src/backend/postmaster/pgarch.c +++ b/src/backend/postmaster/pgarch.c @@ -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); diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index d84bf27757..8df917e4e8 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -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 #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) { diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c index e057666370..87951a6961 100644 --- a/src/backend/postmaster/syslogger.c +++ b/src/backend/postmaster/syslogger.c @@ -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); diff --git a/src/include/postmaster/fork_process.h b/src/include/postmaster/fork_process.h new file mode 100644 index 0000000000..945de36671 --- /dev/null +++ b/src/include/postmaster/fork_process.h @@ -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 */