Final rearrangement of main postgresql child process (ie.

BackendFork/SSDataBase/pgstat) startup, to allow fork/exec calls to
closely mimic (the soon to be provided) Win32 CreateProcess equivalent
calls.

Claudio Natoli
This commit is contained in:
Bruce Momjian 2004-01-06 23:15:22 +00:00
parent 06288d4e22
commit 488f2785d0
6 changed files with 256 additions and 162 deletions

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.172 2003/12/25 03:52:50 momjian Exp $ * $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.173 2004/01/06 23:15:22 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -51,7 +51,7 @@
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
typedef struct Port Port; typedef struct Port Port;
extern void SSDataBaseInit(int); extern void SSDataBaseInit(int);
extern void read_backend_variables(pid_t, Port*); extern void read_backend_variables(unsigned long, Port*);
#endif #endif
extern int Int_yyparse(void); extern int Int_yyparse(void);
@ -231,6 +231,9 @@ BootstrapMain(int argc, char *argv[])
int flag; int flag;
int xlogop = BS_XLOG_NOP; int xlogop = BS_XLOG_NOP;
char *potential_DataDir = NULL; char *potential_DataDir = NULL;
#ifdef EXEC_BACKEND
unsigned long backendID = 0;
#endif
/* /*
* initialize globals * initialize globals
@ -291,10 +294,15 @@ BootstrapMain(int argc, char *argv[])
break; break;
case 'p': case 'p':
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
IsUnderPostmaster = true; {
char buf[MAXPGPATH];
IsUnderPostmaster = true;
sscanf(optarg,"%lu,%s",&backendID,buf);
dbname = strdup(buf);
}
#endif #endif
dbname = strdup(optarg); dbname = strdup(optarg);
break; break;
case 'B': case 'B':
SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV); SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);
break; break;
@ -363,7 +371,7 @@ BootstrapMain(int argc, char *argv[])
{ {
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
read_nondefault_variables(); read_nondefault_variables();
read_backend_variables(getpid(),NULL); read_backend_variables(backendID,NULL);
SSDataBaseInit(xlogop); SSDataBaseInit(xlogop);
#endif #endif
@ -431,11 +439,11 @@ BootstrapMain(int argc, char *argv[])
switch (xlogop) switch (xlogop)
{ {
case BS_XLOG_BGWRITER: case BS_XLOG_BGWRITER:
InitDummyProcess(DUMMY_PROC_BGWRITER); InitDummyProcess(DUMMY_PROC_BGWRITER);
break; break;
default: default:
InitDummyProcess(DUMMY_PROC_DEFAULT); InitDummyProcess(DUMMY_PROC_DEFAULT);
break; break;
} }
} }

View File

@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/main/main.c,v 1.69 2003/12/25 03:52:50 momjian Exp $ * $PostgreSQL: pgsql/src/backend/main/main.c,v 1.70 2004/01/06 23:15:22 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -203,9 +203,9 @@ main(int argc, char *argv[])
/* /*
* Now dispatch to one of PostmasterMain, PostgresMain, GucInfoMain, * Now dispatch to one of PostmasterMain, PostgresMain, GucInfoMain,
* pgstat_main, pgstat_mainChild or BootstrapMain depending on the * SubPostmasterMain, pgstat_main, pgstat_mainChild or BootstrapMain
* program name (and possibly first argument) we were called with. * depending on the program name (and possibly first argument) we
* The lack of consistency here is historical. * were called with. The lack of consistency here is historical.
*/ */
len = strlen(new_argv[0]); len = strlen(new_argv[0]);
@ -223,6 +223,16 @@ main(int argc, char *argv[])
exit(BootstrapMain(argc - 1, new_argv + 1)); exit(BootstrapMain(argc - 1, new_argv + 1));
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
/*
* If the first argument is "-forkexec", then invoke SubPostmasterMain. Note
* we remove "-forkexec" from the arguments passed on to SubPostmasterMain.
*/
if (argc > 1 && strcmp(new_argv[1], "-forkexec") == 0)
{
SubPostmasterMain(argc - 2, new_argv + 2);
exit(0);
}
/* /*
* If the first argument is "-statBuf", then invoke pgstat_main. Note * If the first argument is "-statBuf", then invoke pgstat_main. Note
* we remove "-statBuf" from the arguments passed on to pgstat_main. * we remove "-statBuf" from the arguments passed on to pgstat_main.

View File

@ -13,7 +13,7 @@
* *
* Copyright (c) 2001-2003, PostgreSQL Global Development Group * Copyright (c) 2001-2003, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.50 2003/12/25 03:52:51 momjian Exp $ * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.51 2004/01/06 23:15:22 momjian Exp $
* ---------- * ----------
*/ */
#include "postgres.h" #include "postgres.h"
@ -107,7 +107,7 @@ static char pgStat_fname[MAXPGPATH];
* ---------- * ----------
*/ */
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
static void pgstat_exec(STATS_PROCESS_TYPE procType); static pid_t pgstat_forkexec(STATS_PROCESS_TYPE procType);
static void pgstat_parseArgs(PGSTAT_FORK_ARGS); static void pgstat_parseArgs(PGSTAT_FORK_ARGS);
#endif #endif
NON_EXEC_STATIC void pgstat_main(PGSTAT_FORK_ARGS); NON_EXEC_STATIC void pgstat_main(PGSTAT_FORK_ARGS);
@ -337,15 +337,16 @@ startup_failed:
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
/* ---------- /* ----------
* pgstat_exec() - * pgstat_forkexec() -
* *
* Used to format up the arglist for, and exec, statistics * Used to format up the arglist for, then fork and exec, statistics
* (buffer and collector) processes * (buffer and collector) processes
* *
*/ */
static void static pid_t
pgstat_exec(STATS_PROCESS_TYPE procType) pgstat_forkexec(STATS_PROCESS_TYPE procType)
{ {
pid_t pid;
char *av[11]; char *av[11];
int ac = 0, bufc = 0, i; int ac = 0, bufc = 0, i;
char pgstatBuf[8][MAXPGPATH]; char pgstatBuf[8][MAXPGPATH];
@ -387,9 +388,12 @@ pgstat_exec(STATS_PROCESS_TYPE procType)
av[ac++] = NULL; av[ac++] = NULL;
Assert(ac <= lengthof(av)); Assert(ac <= lengthof(av));
if (execv(pg_pathname,av) == -1) /* Fire off execv in child */
if ((pid = fork()) == 0 && (execv(pg_pathname,av) == -1))
/* FIXME: [fork/exec] suggestions for what to do here? Can't call elog... */ /* FIXME: [fork/exec] suggestions for what to do here? Can't call elog... */
Assert(false); abort();
return pid; /* Parent returns pid */
} }
@ -479,7 +483,11 @@ pgstat_start(void)
beos_before_backend_startup(); beos_before_backend_startup();
#endif #endif
#ifdef EXEC_BACKEND
switch ((pgStatSock = (int) pgstat_forkexec(STAT_PROC_BUFFER)))
#else
switch ((pgStatPid = (int) fork())) switch ((pgStatPid = (int) fork()))
#endif
{ {
case -1: case -1:
#ifdef __BEOS__ #ifdef __BEOS__
@ -490,32 +498,27 @@ pgstat_start(void)
(errmsg("could not fork statistics buffer: %m"))); (errmsg("could not fork statistics buffer: %m")));
return; return;
#ifndef EXEC_BACKEND
case 0: case 0:
/* in postmaster child ... */
#ifdef __BEOS__
/* Specific beos actions after backend startup */
beos_backend_startup();
#endif
/* Close the postmaster's sockets, except for pgstat link */
ClosePostmasterPorts(false);
/* Drop our connection to postmaster's shared memory, as well */
PGSharedMemoryDetach();
pgstat_main();
break; break;
#endif
default: default:
pgstat_is_running = true; pgstat_is_running = true;
return; return;
} }
/* in postmaster child ... */
#ifdef __BEOS__
/* Specific beos actions after backend startup */
beos_backend_startup();
#endif
/* Close the postmaster's sockets, except for pgstat link */
ClosePostmasterPorts(false);
/* Drop our connection to postmaster's shared memory, as well */
PGSharedMemoryDetach();
#ifdef EXEC_BACKEND
pgstat_exec(STAT_PROC_BUFFER);
#else
pgstat_main();
#endif
} }
@ -1385,28 +1388,31 @@ pgstat_main(PGSTAT_FORK_ARGS)
exit(1); exit(1);
} }
#ifdef EXEC_BACKEND
/* child becomes collector process */
switch (pgstat_forkexec(STAT_PROC_COLLECTOR))
#else
switch (fork()) switch (fork())
#endif
{ {
case -1: case -1:
ereport(LOG, ereport(LOG,
(errmsg("could not fork statistics collector: %m"))); (errmsg("could not fork statistics collector: %m")));
exit(1); exit(1);
#ifndef EXEC_BACKEND
case 0: case 0:
/* child becomes collector process */ /* child becomes collector process */
#ifdef EXEC_BACKEND
pgstat_exec(STAT_PROC_COLLECTOR);
#else
pgstat_mainChild(); pgstat_mainChild();
break;
#endif #endif
exit(0);
default: default:
/* parent becomes buffer process */ /* parent becomes buffer process */
closesocket(pgStatPipe[0]); closesocket(pgStatPipe[0]);
pgstat_recvbuffer(); pgstat_recvbuffer();
exit(0);
} }
exit(0);
} }

View File

@ -37,7 +37,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.353 2003/12/25 03:52:51 momjian Exp $ * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.354 2004/01/06 23:15:22 momjian Exp $
* *
* NOTES * NOTES
* *
@ -273,8 +273,8 @@ static void dummy_handler(SIGNAL_ARGS);
static void CleanupProc(int pid, int exitstatus); static void CleanupProc(int pid, int exitstatus);
static void LogChildExit(int lev, const char *procname, static void LogChildExit(int lev, const char *procname,
int pid, int exitstatus); int pid, int exitstatus);
NON_EXEC_STATIC bool BackendInit(Port *port); static void BackendInit(Port *port);
static int BackendFork(Port *port); static int BackendRun(Port *port);
static void ExitPostmaster(int status); static void ExitPostmaster(int status);
static void usage(const char *); static void usage(const char *);
static int ServerLoop(void); static int ServerLoop(void);
@ -297,8 +297,11 @@ postmaster_error(const char *fmt,...)
__attribute__((format(printf, 1, 2))); __attribute__((format(printf, 1, 2)));
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
void read_backend_variables(pid_t pid, Port *port); static pid_t Backend_forkexec(Port *port);
static void write_backend_variables(pid_t pid, Port *port);
static unsigned long tmpBackendFileNum = 0;
void read_backend_variables(unsigned long id, Port *port);
static bool write_backend_variables(Port *port);
#endif #endif
#define StartupDataBase() SSDataBase(BS_XLOG_STARTUP) #define StartupDataBase() SSDataBase(BS_XLOG_STARTUP)
@ -916,7 +919,7 @@ pmdaemonize(int argc, char *argv[])
#endif #endif
#ifdef LINUX_PROFILE #ifdef LINUX_PROFILE
/* see comments in BackendStartup */ /* see comments in BackendRun */
getitimer(ITIMER_PROF, &prof_itimer); getitimer(ITIMER_PROF, &prof_itimer);
#endif #endif
@ -1310,7 +1313,7 @@ ProcessStartupPacket(Port *port, bool SSLdone)
* Now fetch parameters out of startup packet and save them into the * Now fetch parameters out of startup packet and save them into the
* Port structure. All data structures attached to the Port struct * Port structure. All data structures attached to the Port struct
* must be allocated in TopMemoryContext so that they won't disappear * must be allocated in TopMemoryContext so that they won't disappear
* when we pass them to PostgresMain (see BackendFork). We need not * when we pass them to PostgresMain (see BackendRun). We need not
* worry about leaking this storage on failure, since we aren't in the * worry about leaking this storage on failure, since we aren't in the
* postmaster process anymore. * postmaster process anymore.
*/ */
@ -2235,12 +2238,14 @@ BackendStartup(Port *port)
beos_before_backend_startup(); beos_before_backend_startup();
#endif #endif
port->canAcceptConnections = canAcceptConnections();
#ifdef EXEC_BACKEND
pid = Backend_forkexec(port);
#else
pid = fork(); pid = fork();
if (pid == 0) /* child */ if (pid == 0) /* child */
{ {
int status;
#ifdef LINUX_PROFILE #ifdef LINUX_PROFILE
setitimer(ITIMER_PROF, &prof_itimer, NULL); setitimer(ITIMER_PROF, &prof_itimer, NULL);
#endif #endif
@ -2251,13 +2256,9 @@ BackendStartup(Port *port)
#endif #endif
free(bn); free(bn);
status = BackendFork(port); proc_exit(BackendRun(port));
if (status != 0)
ereport(LOG,
(errmsg("connection startup failed")));
proc_exit(status);
} }
#endif
/* in parent, error */ /* in parent, error */
if (pid < 0) if (pid < 0)
@ -2349,15 +2350,15 @@ split_opts(char **argv, int *argcp, char *s)
/* /*
* BackendInit/Fork -- perform authentication [BackendInit], and if successful, * BackendInit/Run -- perform authentication [BackendInit], and if successful,
* set up the backend's argument list [BackendFork] and invoke * set up the backend's argument list [BackendRun] and invoke
* backend main() [or exec in EXEC_BACKEND case] * backend main()
* *
* returns: * returns:
* Shouldn't return at all. * Shouldn't return at all.
* If PostgresMain() fails, return status. * If PostgresMain() fails, return status.
*/ */
NON_EXEC_STATIC bool static void
BackendInit(Port *port) BackendInit(Port *port)
{ {
int status; int status;
@ -2447,7 +2448,11 @@ BackendInit(Port *port)
status = ProcessStartupPacket(port, false); status = ProcessStartupPacket(port, false);
if (status != STATUS_OK) if (status != STATUS_OK)
return false; /* cancel request processed, or error */ {
ereport(LOG,
(errmsg("connection startup failed")));
proc_exit(status);
}
/* /*
* Now that we have the user and database name, we can set the process * Now that we have the user and database name, we can set the process
@ -2483,27 +2488,18 @@ BackendInit(Port *port)
random_seed = 0; random_seed = 0;
gettimeofday(&now, &tz); gettimeofday(&now, &tz);
srandom((unsigned int) now.tv_usec); srandom((unsigned int) now.tv_usec);
#ifdef EXEC_BACKEND
ClientAuthInProgress = false; /* client_min_messages is active
* now */
#endif
return true;
} }
static int static int
BackendFork(Port *port) BackendRun(Port *port)
{ {
char **av; char **av;
int maxac; int maxac;
int ac; int ac;
char debugbuf[32]; char debugbuf[32];
#ifndef EXEC_BACKEND
char protobuf[32]; char protobuf[32];
#endif
int i; int i;
char tmpExtraOptions[MAXPGPATH];
/* /*
* Let's clean up ourselves as the postmaster child, and * Let's clean up ourselves as the postmaster child, and
@ -2521,12 +2517,9 @@ BackendFork(Port *port)
if (PreAuthDelay > 0) if (PreAuthDelay > 0)
sleep(PreAuthDelay); sleep(PreAuthDelay);
port->canAcceptConnections = canAcceptConnections(); /* Will exit on failure */
BackendInit(port);
#ifndef EXEC_BACKEND
if (!BackendInit(port))
return -1;
#endif
/* ---------------- /* ----------------
* Now, build the argv vector that will be given to PostgresMain. * Now, build the argv vector that will be given to PostgresMain.
@ -2563,48 +2556,30 @@ BackendFork(Port *port)
/* /*
* Pass any backend switches specified with -o in the postmaster's own * Pass any backend switches specified with -o in the postmaster's own
* command line. We assume these are secure. * command line. We assume these are secure.
* [Note: now makes a copy to protect against future fork/exec changes]
*/ */
strcpy(tmpExtraOptions,ExtraOptions); split_opts(av, &ac, ExtraOptions);
split_opts(av, &ac, tmpExtraOptions);
#ifndef EXEC_BACKEND
/* Tell the backend what protocol the frontend is using. */ /* Tell the backend what protocol the frontend is using. */
snprintf(protobuf, sizeof(protobuf), "-v%u", port->proto); snprintf(protobuf, sizeof(protobuf), "-v%u", port->proto);
av[ac++] = protobuf; av[ac++] = protobuf;
#ifdef EXEC_BACKEND
/* pass data dir before end of secure switches (-p) */
av[ac++] = "-D";
av[ac++] = DataDir;
#endif #endif
/* /*
* Tell the backend it is being called from the postmaster, and which * Tell the backend it is being called from the postmaster, and which
* database to use. -p marks the end of secure switches. * database to use. -p marks the end of secure switches.
*/ */
#ifdef EXEC_BACKEND
write_backend_variables(getpid(),port);
/* pass data dir before end of secure switches (-p) */
av[ac++] = "-D";
av[ac++] = DataDir;
/*
* This is totally bogus. We need to pass an arg to -p, but we'll
* actually get the dbname by ProcessStartupPacket in the exec'd
* process
*/
av[ac++] = "-p";
av[ac++] = "FORK_EXEC";
#else
av[ac++] = "-p"; av[ac++] = "-p";
av[ac++] = port->database_name; av[ac++] = port->database_name;
#endif
/* /*
* Pass the (insecure) option switches from the connection request. * Pass the (insecure) option switches from the connection request.
* (It's OK to mangle port->cmdline_options now.) * (It's OK to mangle port->cmdline_options now.)
*/ */
/* FIXME: [fork/exec] Hmmm.. we won't see these until after we BackendInit.
* Should we add code to BackendInit to add these (somehow!) into
* the PostgresMain argument list in the EXEC_BACKEND case?
*/
if (port->cmdline_options) if (port->cmdline_options)
split_opts(av, &ac, port->cmdline_options); split_opts(av, &ac, port->cmdline_options);
@ -2620,7 +2595,9 @@ BackendFork(Port *port)
* username isn't lost either; see ProcessStartupPacket(). * username isn't lost either; see ProcessStartupPacket().
*/ */
MemoryContextSwitchTo(TopMemoryContext); MemoryContextSwitchTo(TopMemoryContext);
#ifndef EXEC_BACKEND
MemoryContextDelete(PostmasterContext); MemoryContextDelete(PostmasterContext);
#endif
PostmasterContext = NULL; PostmasterContext = NULL;
/* /*
@ -2635,16 +2612,105 @@ BackendFork(Port *port)
ereport(DEBUG3, ereport(DEBUG3,
(errmsg_internal(")"))); (errmsg_internal(")")));
#ifdef EXEC_BACKEND
return execv(pg_pathname,av);
#else
ClientAuthInProgress = false; /* client_min_messages is active ClientAuthInProgress = false; /* client_min_messages is active
* now */ * now */
return (PostgresMain(ac, av, port->user_name)); return (PostgresMain(ac, av, port->user_name));
#endif
} }
#ifdef EXEC_BACKEND
/*
* SubPostmasterMain -- prepare the fork/exec'd process to be in an equivalent
* state (for calling BackendRun) as a forked process.
*
* returns:
* Shouldn't return at all.
*/
void
SubPostmasterMain(int argc, char* argv[])
{
unsigned long backendID;
Port port;
memset((void*)&port, 0, sizeof(Port));
Assert(argc == 2);
/* Setup global context */
MemoryContextInit();
InitializeGUCOptions();
/* Parse passed-in context */
argc = 0;
backendID = (unsigned long)atol(argv[argc++]);
DataDir = strdup(argv[argc++]);
/* Read in file-based context */
read_nondefault_variables();
read_backend_variables(backendID,&port);
/* FIXME: [fork/exec] Ugh */
load_hba();
load_ident();
load_user();
load_group();
/* Run backend */
proc_exit(BackendRun(&port));
}
/*
* Backend_forkexec -- fork/exec off a backend process
*
* returns:
* the pid of the fork/exec'd process
*/
static pid_t
Backend_forkexec(Port *port)
{
pid_t pid;
char *av[5];
int ac = 0, bufc = 0, i;
char buf[2][MAXPGPATH];
if (!write_backend_variables(port))
return -1; /* log made by write_backend_variables */
av[ac++] = "postgres";
av[ac++] = "-forkexec";
/* Format up context to pass to exec'd process */
snprintf(buf[bufc++],MAXPGPATH,"%lu",tmpBackendFileNum);
/* FIXME: [fork/exec] whitespaces in directories? */
snprintf(buf[bufc++],MAXPGPATH,"%s",DataDir);
/* Add to the arg list */
Assert(bufc <= lengthof(buf));
for (i = 0; i < bufc; i++)
av[ac++] = buf[i];
/* FIXME: [fork/exec] ExtraOptions? */
av[ac++] = NULL;
Assert(ac <= lengthof(av));
/* Fire off execv in child */
if ((pid = fork()) == 0 && (execv(pg_pathname,av) == -1))
/*
* FIXME: [fork/exec] suggestions for what to do here?
* Probably OK to issue error (unlike pgstat case)
*/
abort();
return pid; /* Parent returns pid */
}
#endif
/* /*
* ExitPostmaster -- cleanup * ExitPostmaster -- cleanup
* *
@ -2851,6 +2917,9 @@ CountChildren(void)
* *
* Return value of SSDataBase is subprocess' PID, or 0 if failed to start subprocess * Return value of SSDataBase is subprocess' PID, or 0 if failed to start subprocess
* (0 is returned only for checkpoint case). * (0 is returned only for checkpoint case).
*
* note: in the EXEC_BACKEND case, we delay the fork until argument list has been
* established
*/ */
NON_EXEC_STATIC void NON_EXEC_STATIC void
SSDataBaseInit(int xlop) SSDataBaseInit(int xlop)
@ -2894,16 +2963,20 @@ SSDataBase(int xlop)
{ {
pid_t pid; pid_t pid;
Backend *bn; Backend *bn;
#ifndef EXEC_BACKEND
#ifdef LINUX_PROFILE #ifdef LINUX_PROFILE
struct itimerval prof_itimer; struct itimerval prof_itimer;
#endif #endif
#else
char idbuf[32];
#endif
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
#ifndef EXEC_BACKEND
#ifdef LINUX_PROFILE #ifdef LINUX_PROFILE
/* see comments in BackendStartup */ /* see comments in BackendRun */
getitimer(ITIMER_PROF, &prof_itimer); getitimer(ITIMER_PROF, &prof_itimer);
#endif #endif
@ -2912,13 +2985,16 @@ SSDataBase(int xlop)
beos_before_backend_startup(); beos_before_backend_startup();
#endif #endif
/* Non EXEC_BACKEND case; fork here */
if ((pid = fork()) == 0) /* child */ if ((pid = fork()) == 0) /* child */
#endif
{ {
char *av[10]; char *av[10];
int ac = 0; int ac = 0;
char nbbuf[32]; char nbbuf[32];
char xlbuf[32]; char xlbuf[32];
#ifndef EXEC_BACKEND
#ifdef LINUX_PROFILE #ifdef LINUX_PROFILE
setitimer(ITIMER_PROF, &prof_itimer, NULL); setitimer(ITIMER_PROF, &prof_itimer, NULL);
#endif #endif
@ -2931,8 +3007,10 @@ SSDataBase(int xlop)
/* Close the postmaster's sockets */ /* Close the postmaster's sockets */
ClosePostmasterPorts(true); ClosePostmasterPorts(true);
#ifndef EXEC_BACKEND
SSDataBaseInit(xlop); SSDataBaseInit(xlop);
#else
if (!write_backend_variables(NULL))
return -1; /* log issued by write_backend_variables */
#endif #endif
/* Set up command-line arguments for subprocess */ /* Set up command-line arguments for subprocess */
@ -2941,7 +3019,6 @@ SSDataBase(int xlop)
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
av[ac++] = "-boot"; av[ac++] = "-boot";
#endif #endif
snprintf(nbbuf, sizeof(nbbuf), "-B%d", NBuffers); snprintf(nbbuf, sizeof(nbbuf), "-B%d", NBuffers);
av[ac++] = nbbuf; av[ac++] = nbbuf;
@ -2949,22 +3026,30 @@ SSDataBase(int xlop)
av[ac++] = xlbuf; av[ac++] = xlbuf;
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
write_backend_variables(getpid(),NULL);
/* pass data dir before end of secure switches (-p) */ /* pass data dir before end of secure switches (-p) */
av[ac++] = "-D"; av[ac++] = "-D";
av[ac++] = DataDir; av[ac++] = DataDir;
#endif
/* and the backend identifier + dbname */
snprintf(idbuf, sizeof(idbuf), "-p%lu,template1", tmpBackendFileNum);
av[ac++] = idbuf;
#else
av[ac++] = "-p"; av[ac++] = "-p";
av[ac++] = "template1"; av[ac++] = "template1";
#endif
av[ac] = (char *) NULL; av[ac] = (char *) NULL;
Assert(ac < lengthof(av)); Assert(ac < lengthof(av));
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
if (execv(pg_pathname,av) == -1) /* EXEC_BACKEND case; fork/exec here */
elog(FATAL,"unable to execv in SSDataBase: %m"); if ((pid = fork()) == 0 && (execv(pg_pathname,av) == -1))
{
/* in child */
elog(ERROR,"unable to execv in SSDataBase: %m");
exit(0);
}
#else #else
BootstrapMain(ac, av); BootstrapMain(ac, av);
ExitPostmaster(0); ExitPostmaster(0);
@ -2974,11 +3059,12 @@ SSDataBase(int xlop)
/* in parent */ /* in parent */
if (pid < 0) if (pid < 0)
{ {
#ifndef EXEC_BACKEND
#ifdef __BEOS__ #ifdef __BEOS__
/* Specific beos actions before backend startup */ /* Specific beos actions before backend startup */
beos_backend_startup_failed(); beos_backend_startup_failed();
#endif #endif
#endif
switch (xlop) switch (xlop)
{ {
case BS_XLOG_STARTUP: case BS_XLOG_STARTUP:
@ -3111,6 +3197,7 @@ postmaster_error(const char *fmt,...)
* The following need to be available to the read/write_backend_variables * The following need to be available to the read/write_backend_variables
* functions * functions
*/ */
#include "storage/spin.h"
extern XLogRecPtr RedoRecPtr; extern XLogRecPtr RedoRecPtr;
extern XLogwrtResult LogwrtResult; extern XLogwrtResult LogwrtResult;
extern slock_t *ShmemLock; extern slock_t *ShmemLock;
@ -3124,22 +3211,22 @@ extern int pgStatSock;
#define write_var(var,fp) fwrite((void*)&(var),sizeof(var),1,fp) #define write_var(var,fp) fwrite((void*)&(var),sizeof(var),1,fp)
#define read_var(var,fp) fread((void*)&(var),sizeof(var),1,fp) #define read_var(var,fp) fread((void*)&(var),sizeof(var),1,fp)
#define get_tmp_backend_file_name(buf,id) \ #define get_tmp_backend_file_name(buf,id) \
do { \ do { \
Assert(DataDir); \ Assert(DataDir); \
sprintf((buf), \ sprintf((buf), \
"%s/%s/%s.backend_var.%d", \ "%s/%s/%s.backend_var.%lu", \
DataDir, \ DataDir, \
PG_TEMP_FILES_DIR, \ PG_TEMP_FILES_DIR, \
PG_TEMP_FILE_PREFIX, \ PG_TEMP_FILE_PREFIX, \
(id)); \ (id)); \
} while (0) } while (0)
static void static bool
write_backend_variables(pid_t pid, Port *port) write_backend_variables(Port *port)
{ {
char filename[MAXPGPATH]; char filename[MAXPGPATH];
FILE *fp; FILE *fp;
get_tmp_backend_file_name(filename,pid); get_tmp_backend_file_name(filename,++tmpBackendFileNum);
/* Open file */ /* Open file */
fp = AllocateFile(filename, PG_BINARY_W); fp = AllocateFile(filename, PG_BINARY_W);
@ -3156,7 +3243,7 @@ write_backend_variables(pid_t pid, Port *port)
ereport(ERROR, ereport(ERROR,
(errcode_for_file_access(), (errcode_for_file_access(),
errmsg("could not write to file \"%s\": %m", filename))); errmsg("could not write to file \"%s\": %m", filename)));
return; return false;
} }
} }
@ -3188,16 +3275,20 @@ write_backend_variables(pid_t pid, Port *port)
write_var(ProcStructLock,fp); write_var(ProcStructLock,fp);
write_var(pgStatSock,fp); write_var(pgStatSock,fp);
write_var(PreAuthDelay,fp);
write_var(debug_flag,fp);
/* Release file */ /* Release file */
FreeFile(fp); FreeFile(fp);
return true;
} }
void void
read_backend_variables(pid_t pid, Port *port) read_backend_variables(unsigned long id, Port *port)
{ {
char filename[MAXPGPATH]; char filename[MAXPGPATH];
FILE *fp; FILE *fp;
get_tmp_backend_file_name(filename,pid); get_tmp_backend_file_name(filename,id);
/* Open file */ /* Open file */
fp = AllocateFile(filename, PG_BINARY_R); fp = AllocateFile(filename, PG_BINARY_R);
@ -3237,6 +3328,9 @@ read_backend_variables(pid_t pid, Port *port)
read_var(ProcStructLock,fp); read_var(ProcStructLock,fp);
read_var(pgStatSock,fp); read_var(pgStatSock,fp);
read_var(PreAuthDelay,fp);
read_var(debug_flag,fp);
/* Release file */ /* Release file */
FreeFile(fp); FreeFile(fp);
if (unlink(filename) != 0) if (unlink(filename) != 0)

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.382 2004/01/06 17:36:31 neilc Exp $ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.383 2004/01/06 23:15:22 momjian Exp $
* *
* NOTES * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
@ -68,11 +68,6 @@
extern int optind; extern int optind;
extern char *optarg; extern char *optarg;
#ifdef EXEC_BACKEND
extern bool BackendInit(Port*);
extern void read_backend_variables(pid_t, Port*);
#endif
/* ---------------- /* ----------------
* global variables * global variables
* ---------------- * ----------------
@ -2063,7 +2058,7 @@ PostgresMain(int argc, char *argv[], const char *username)
* *
* If we are running under the postmaster, this is done already. * If we are running under the postmaster, this is done already.
*/ */
if (!IsUnderPostmaster || ExecBackend) if (!IsUnderPostmaster)
MemoryContextInit(); MemoryContextInit();
set_ps_display("startup"); set_ps_display("startup");
@ -2268,11 +2263,7 @@ PostgresMain(int argc, char *argv[], const char *username)
*/ */
if (secure) if (secure)
{ {
#ifdef EXEC_BACKEND
IsUnderPostmaster = true;
#else
dbname = strdup(optarg); dbname = strdup(optarg);
#endif
secure = false; /* subsequent switches are NOT secure = false; /* subsequent switches are NOT
* secure */ * secure */
@ -2478,25 +2469,7 @@ PostgresMain(int argc, char *argv[], const char *username)
if (IsUnderPostmaster) if (IsUnderPostmaster)
{ {
#ifdef EXEC_BACKEND #ifdef EXEC_BACKEND
Port *port =(Port*)malloc(sizeof(Port));
if (port == NULL)
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("insufficient memory to allocate port")));
read_nondefault_variables(); read_nondefault_variables();
read_backend_variables(getpid(),port);
/* FIXME: [fork/exec] Ugh */
load_hba();
load_ident();
load_user();
load_group();
if (!BackendInit(port))
return -1;
dbname = port->database_name;
#endif #endif
} else } else
ProcessConfigFile(PGC_POSTMASTER); ProcessConfigFile(PGC_POSTMASTER);

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.141 2004/01/06 17:36:31 neilc Exp $ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.142 2004/01/06 23:15:22 momjian Exp $
* *
* NOTES * NOTES
* some of the information in this file should be moved to * some of the information in this file should be moved to
@ -115,6 +115,9 @@ extern bool ClientAuthInProgress;
extern const bool ExecBackend; extern const bool ExecBackend;
extern int PostmasterMain(int argc, char *argv[]); extern int PostmasterMain(int argc, char *argv[]);
#ifdef EXEC_BACKEND
extern void SubPostmasterMain(int argc, char* argv[]);
#endif
extern void ClosePostmasterPorts(bool pgstat_too); extern void ClosePostmasterPorts(bool pgstat_too);
/* /*