提交 36fa2974 编写于 作者: B Bruce Momjian

SECOND ATTEMPT

Dump/read non-default GUC values for use by exec'ed backend, for Win32.
上级 9f0d69f5
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.318 2003/05/02 22:01:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.319 2003/05/02 22:02:47 momjian Exp $
* *
* NOTES * NOTES
* *
...@@ -256,11 +256,12 @@ static void dummy_handler(SIGNAL_ARGS); ...@@ -256,11 +256,12 @@ 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);
static int DoBackend(Port *port); static int BackendFinalize(Port *port);
void ExitPostmaster(int status); void ExitPostmaster(int status);
static void usage(const char *); static void usage(const char *);
static int ServerLoop(void); static int ServerLoop(void);
static int BackendStartup(Port *port); static int BackendStartup(Port *port);
static void BackendFork(Port *port, Backend *bn);
static int ProcessStartupPacket(Port *port, bool SSLdone); static int ProcessStartupPacket(Port *port, bool SSLdone);
static void processCancelRequest(Port *port, void *pkt); static void processCancelRequest(Port *port, void *pkt);
static int initMasks(fd_set *rmask, fd_set *wmask); static int initMasks(fd_set *rmask, fd_set *wmask);
...@@ -570,6 +571,9 @@ PostmasterMain(int argc, char *argv[]) ...@@ -570,6 +571,9 @@ PostmasterMain(int argc, char *argv[])
SetDataDir(potential_DataDir); SetDataDir(potential_DataDir);
ProcessConfigFile(PGC_POSTMASTER); ProcessConfigFile(PGC_POSTMASTER);
#ifdef EXEC_BACKEND
write_nondefault_variables(PGC_POSTMASTER);
#endif
/* /*
* Check for invalid combinations of GUC settings. * Check for invalid combinations of GUC settings.
...@@ -1231,7 +1235,7 @@ ProcessStartupPacket(Port *port, bool SSLdone) ...@@ -1231,7 +1235,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 DoBackend). We need not worry * when we pass them to PostgresMain (see BackendFinalize). We need not worry
* about leaking this storage on failure, since we aren't in the postmaster * about leaking this storage on failure, since we aren't in the postmaster
* process anymore. * process anymore.
*/ */
...@@ -1568,6 +1572,9 @@ SIGHUP_handler(SIGNAL_ARGS) ...@@ -1568,6 +1572,9 @@ SIGHUP_handler(SIGNAL_ARGS)
elog(LOG, "Received SIGHUP, reloading configuration files"); elog(LOG, "Received SIGHUP, reloading configuration files");
SignalChildren(SIGHUP); SignalChildren(SIGHUP);
ProcessConfigFile(PGC_SIGHUP); ProcessConfigFile(PGC_SIGHUP);
#ifdef EXEC_BACKEND
write_nondefault_variables(PGC_SIGHUP);
#endif
load_hba(); load_hba();
load_ident(); load_ident();
} }
...@@ -2053,28 +2060,7 @@ BackendStartup(Port *port) ...@@ -2053,28 +2060,7 @@ BackendStartup(Port *port)
pid = fork(); pid = fork();
if (pid == 0) /* child */ if (pid == 0) /* child */
{ BackendFork(port, bn); /* never returns */
int status;
#ifdef LINUX_PROFILE
setitimer(ITIMER_PROF, &prof_itimer, NULL);
#endif
#ifdef __BEOS__
/* Specific beos backend startup actions */
beos_backend_startup();
#endif
free(bn);
status = DoBackend(port);
if (status != 0)
{
elog(LOG, "connection startup failed");
proc_exit(status);
}
else
proc_exit(0);
}
/* in parent, error */ /* in parent, error */
if (pid < 0) if (pid < 0)
...@@ -2108,6 +2094,31 @@ BackendStartup(Port *port) ...@@ -2108,6 +2094,31 @@ BackendStartup(Port *port)
} }
static void
BackendFork(Port *port, Backend *bn)
{
int status;
#ifdef LINUX_PROFILE
setitimer(ITIMER_PROF, &prof_itimer, NULL);
#endif
#ifdef __BEOS__
/* Specific beos backend startup actions */
beos_backend_startup();
#endif
free(bn);
status = BackendFinalize(port);
if (status != 0)
{
elog(LOG, "connection startup failed");
proc_exit(status);
}
else
proc_exit(0);
}
/* /*
* Try to report backend fork() failure to client before we close the * Try to report backend fork() failure to client before we close the
* connection. Since we do not care to risk blocking the postmaster on * connection. Since we do not care to risk blocking the postmaster on
...@@ -2173,7 +2184,7 @@ split_opts(char **argv, int *argcp, char *s) ...@@ -2173,7 +2184,7 @@ split_opts(char **argv, int *argcp, char *s)
} }
/* /*
* DoBackend -- perform authentication, and if successful, set up the * BackendFinalize -- perform authentication, and if successful, set up the
* backend's argument list and invoke backend main(). * backend's argument list and invoke backend main().
* *
* This used to perform an execv() but we no longer exec the backend; * This used to perform an execv() but we no longer exec the backend;
...@@ -2184,7 +2195,7 @@ split_opts(char **argv, int *argcp, char *s) ...@@ -2184,7 +2195,7 @@ split_opts(char **argv, int *argcp, char *s)
* If PostgresMain() fails, return status. * If PostgresMain() fails, return status.
*/ */
static int static int
DoBackend(Port *port) BackendFinalize(Port *port)
{ {
char *remote_host; char *remote_host;
char **av; char **av;
...@@ -2221,6 +2232,10 @@ DoBackend(Port *port) ...@@ -2221,6 +2232,10 @@ DoBackend(Port *port)
/* Reset MyProcPid to new backend's pid */ /* Reset MyProcPid to new backend's pid */
MyProcPid = getpid(); MyProcPid = getpid();
#ifdef EXEC_BACKEND
read_nondefault_variables();
#endif
/* /*
* Initialize libpq and enable reporting of elog errors to the client. * Initialize libpq and enable reporting of elog errors to the client.
* Must do this now because authentication uses libpq to send * Must do this now because authentication uses libpq to send
...@@ -2248,7 +2263,7 @@ DoBackend(Port *port) ...@@ -2248,7 +2263,7 @@ DoBackend(Port *port)
unsigned short remote_port; unsigned short remote_port;
char *host_addr; char *host_addr;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
char ip_hostinfo[INET6_ADDRSTRLEN]; char ip_hostinfo[INET6_ADDRSTRLEN];
#else #else
char ip_hostinfo[INET_ADDRSTRLEN]; char ip_hostinfo[INET_ADDRSTRLEN];
#endif #endif
...@@ -2294,7 +2309,7 @@ DoBackend(Port *port) ...@@ -2294,7 +2309,7 @@ DoBackend(Port *port)
} }
else else
{ {
/* not AF_INET */ /* not AF_INET */
remote_host = "[local]"; remote_host = "[local]";
if (Log_connections) if (Log_connections)
...@@ -2318,7 +2333,7 @@ DoBackend(Port *port) ...@@ -2318,7 +2333,7 @@ DoBackend(Port *port)
* indefinitely. PreAuthDelay doesn't count against the time limit. * indefinitely. PreAuthDelay doesn't count against the time limit.
*/ */
if (!enable_sig_alarm(AuthenticationTimeout * 1000, false)) if (!enable_sig_alarm(AuthenticationTimeout * 1000, false))
elog(FATAL, "DoBackend: Unable to set timer for auth timeout"); elog(FATAL, "BackendFinalize: Unable to set timer for auth timeout");
/* /*
* Receive the startup packet (which might turn out to be a cancel * Receive the startup packet (which might turn out to be a cancel
...@@ -2347,7 +2362,7 @@ DoBackend(Port *port) ...@@ -2347,7 +2362,7 @@ DoBackend(Port *port)
* SIGTERM/SIGQUIT again until backend startup is complete. * SIGTERM/SIGQUIT again until backend startup is complete.
*/ */
if (!disable_sig_alarm(false)) if (!disable_sig_alarm(false))
elog(FATAL, "DoBackend: Unable to disable timer for auth timeout"); elog(FATAL, "BackendFinalize: Unable to disable timer for auth timeout");
PG_SETMASK(&BlockSig); PG_SETMASK(&BlockSig);
if (Log_connections) if (Log_connections)
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.121 2003/05/02 22:01:51 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.122 2003/05/02 22:02:47 momjian Exp $
* *
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
...@@ -60,6 +60,9 @@ ...@@ -60,6 +60,9 @@
#define PG_KRB_SRVTAB "" #define PG_KRB_SRVTAB ""
#endif #endif
#ifdef EXEC_BACKEND
#define CONFIG_EXEC_PARAMS "global/config_exec_params"
#endif
/* XXX these should appear in other modules' header files */ /* XXX these should appear in other modules' header files */
extern bool Log_connections; extern bool Log_connections;
...@@ -2801,6 +2804,204 @@ _ShowOption(struct config_generic * record) ...@@ -2801,6 +2804,204 @@ _ShowOption(struct config_generic * record)
} }
#ifdef EXEC_BACKEND
/*
* This routine dumps out all non-default GUC options into a binary
* file that is read by all exec'ed backends. The format is:
*
* variable name, string, null terminated
* variable value, string, null terminated
* variable source, integer
*/
void
write_nondefault_variables(GucContext context)
{
int i;
char *new_filename, *filename;
int elevel;
FILE *fp;
Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
Assert(DataDir);
elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR;
/*
* Open file
*/
new_filename = malloc(strlen(DataDir) + strlen(CONFIG_EXEC_PARAMS) +
strlen(".new") + 2);
filename = malloc(strlen(DataDir) + strlen(CONFIG_EXEC_PARAMS) + 2);
if (new_filename == NULL || filename == NULL)
{
elog(elevel, "out of memory");
return;
}
sprintf(new_filename, "%s/" CONFIG_EXEC_PARAMS ".new", DataDir);
sprintf(filename, "%s/" CONFIG_EXEC_PARAMS, DataDir);
fp = AllocateFile(new_filename, "w");
if (!fp)
{
free(new_filename);
free(filename);
elog(elevel, "could not write exec config params file `"
CONFIG_EXEC_PARAMS "': %s", strerror(errno));
return;
}
for (i = 0; i < num_guc_variables; i++)
{
struct config_generic *gconf = guc_variables[i];
if (gconf->source != PGC_S_DEFAULT)
{
fprintf(fp, "%s", gconf->name);
fputc(0, fp);
switch (gconf->vartype)
{
case PGC_BOOL:
{
struct config_bool *conf = (struct config_bool *) gconf;
if (*conf->variable == 0)
fprintf(fp, "false");
else
fprintf(fp, "true");
}
break;
case PGC_INT:
{
struct config_int *conf = (struct config_int *) gconf;
fprintf(fp, "%d", *conf->variable);
}
break;
case PGC_REAL:
{
struct config_real *conf = (struct config_real *) gconf;
/* Could lose precision here? */
fprintf(fp, "%f", *conf->variable);
}
break;
case PGC_STRING:
{
struct config_string *conf = (struct config_string *) gconf;
fprintf(fp, "%s", *conf->variable);
}
break;
}
fputc(0, fp);
fwrite(&gconf->source, sizeof(gconf->source), 1, fp);
}
}
FreeFile(fp);
/* Put new file in place, this could delay on Win32 */
rename(new_filename, filename);
free(new_filename);
free(filename);
return;
}
/*
* Read string, including null byte from file
*
* Return NULL on EOF and nothing read
*/
static char *
read_string_with_null(FILE *fp)
{
int i = 0, ch, maxlen = 256;
char *str = NULL;
do
{
if ((ch = fgetc(fp)) == EOF)
{
if (i == 0)
return NULL;
else
elog(FATAL, "Invalid format of exec config params file");
}
if (i == 0)
str = malloc(maxlen);
else if (i == maxlen)
str = realloc(str, maxlen *= 2);
str[i++] = ch;
} while (ch != 0);
return str;
}
/*
* This routine loads a previous postmaster dump of its non-default
* settings.
*/
void
read_nondefault_variables(void)
{
char *filename;
FILE *fp;
char *varname, *varvalue;
int varsource;
Assert(DataDir);
/*
* Open file
*/
filename = malloc(strlen(DataDir) + strlen(CONFIG_EXEC_PARAMS) + 2);
if (filename == NULL)
{
elog(ERROR, "out of memory");
return;
}
sprintf(filename, "%s/" CONFIG_EXEC_PARAMS, DataDir);
fp = AllocateFile(filename, "r");
if (!fp)
{
free(filename);
/* File not found is fine */
if (errno != ENOENT)
elog(FATAL, "could not read exec config params file `"
CONFIG_EXEC_PARAMS "': %s", strerror(errno));
return;
}
while (1)
{
if ((varname = read_string_with_null(fp)) == NULL)
break;
if ((varvalue = read_string_with_null(fp)) == NULL)
elog(FATAL, "Invalid format of exec config params file");
if (fread(&varsource, sizeof(varsource), 1, fp) == 0)
elog(FATAL, "Invalid format of exec config params file");
(void) set_config_option(varname, varvalue, PGC_POSTMASTER,
varsource, false, true);
free(varname);
free(varvalue);
}
FreeFile(fp);
free(filename);
return;
}
#endif
/* /*
* A little "long argument" simulation, although not quite GNU * A little "long argument" simulation, although not quite GNU
* compliant. Takes a string of the form "some-option=some value" and * compliant. Takes a string of the form "some-option=some value" and
...@@ -3203,3 +3404,4 @@ assign_msglvl(int *var, const char *newval, bool doit, bool interactive) ...@@ -3203,3 +3404,4 @@ assign_msglvl(int *var, const char *newval, bool doit, bool interactive)
#include "guc-file.c" #include "guc-file.c"
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright 2000-2003 by PostgreSQL Global Development Group * Copyright 2000-2003 by PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
* *
* $Id: guc.h,v 1.29 2003/05/02 22:01:51 momjian Exp $ * $Id: guc.h,v 1.30 2003/05/02 22:02:47 momjian Exp $
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
#ifndef GUC_H #ifndef GUC_H
...@@ -135,4 +135,9 @@ extern void ProcessGUCArray(ArrayType *array, GucSource source); ...@@ -135,4 +135,9 @@ extern void ProcessGUCArray(ArrayType *array, GucSource source);
extern ArrayType *GUCArrayAdd(ArrayType *array, const char *name, const char *value); extern ArrayType *GUCArrayAdd(ArrayType *array, const char *name, const char *value);
extern ArrayType *GUCArrayDelete(ArrayType *array, const char *name); extern ArrayType *GUCArrayDelete(ArrayType *array, const char *name);
#ifdef EXEC_BACKEND
void write_nondefault_variables(GucContext context);
void read_nondefault_variables(void);
#endif
#endif /* GUC_H */ #endif /* GUC_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册