1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-26 12:21:12 +03:00

Fix management of pendingOpsTable in auxiliary processes.

mdinit() was misusing IsBootstrapProcessingMode() to decide whether to
create an fsync pending-operations table in the current process.  This led
to creating a table not only in the startup and checkpointer processes as
intended, but also in the bgwriter process, not to mention other auxiliary
processes such as walwriter and walreceiver.  Creation of the table in the
bgwriter is fatal, because it absorbs fsync requests that should have gone
to the checkpointer; instead they just sit in bgwriter local memory and are
never acted on.  So writes performed by the bgwriter were not being fsync'd
which could result in data loss after an OS crash.  I think there is no
live bug with respect to walwriter and walreceiver because those never
perform any writes of shared buffers; but the potential is there for
future breakage in those processes too.

To fix, make AuxiliaryProcessMain() export the current process's
AuxProcType as a global variable, and then make mdinit() test directly for
the types of aux process that should have a pendingOpsTable.  Having done
that, we might as well also get rid of the random bool flags such as
am_walreceiver that some of the aux processes had grown.  (Note that we
could not have fixed the bug by examining those variables in mdinit(),
because it's called from BaseInit() which is run by AuxiliaryProcessMain()
before entering any of the process-type-specific code.)

Back-patch to 9.2, where the problem was introduced by the split-up of
bgwriter and checkpointer processes.  The bogus pendingOpsTable exists
in walwriter and walreceiver processes in earlier branches, but absent
any evidence that it causes actual problems there, I'll leave the older
branches alone.
This commit is contained in:
Tom Lane
2012-07-18 15:28:10 -04:00
parent 3855968f32
commit 4a9c30a8a1
11 changed files with 62 additions and 57 deletions

View File

@ -63,6 +63,8 @@ static void cleanup(void);
* ----------------
*/
AuxProcType MyAuxProcType = NotAnAuxProcess; /* declared in miscadmin.h */
Relation boot_reldesc; /* current relation descriptor */
Form_pg_attribute attrtypes[MAXATTR]; /* points to attribute info */
@ -187,7 +189,6 @@ AuxiliaryProcessMain(int argc, char *argv[])
{
char *progname = argv[0];
int flag;
AuxProcType auxType = CheckerProcess;
char *userDoption = NULL;
/*
@ -228,6 +229,9 @@ AuxiliaryProcessMain(int argc, char *argv[])
argc--;
}
/* If no -x argument, we are a CheckerProcess */
MyAuxProcType = CheckerProcess;
while ((flag = getopt(argc, argv, "B:c:d:D:Fr:x:-:")) != -1)
{
switch (flag)
@ -258,7 +262,7 @@ AuxiliaryProcessMain(int argc, char *argv[])
strlcpy(OutputFileName, optarg, MAXPGPATH);
break;
case 'x':
auxType = atoi(optarg);
MyAuxProcType = atoi(optarg);
break;
case 'c':
case '-':
@ -308,7 +312,7 @@ AuxiliaryProcessMain(int argc, char *argv[])
{
const char *statmsg;
switch (auxType)
switch (MyAuxProcType)
{
case StartupProcess:
statmsg = "startup process";
@ -374,15 +378,15 @@ AuxiliaryProcessMain(int argc, char *argv[])
/*
* Assign the ProcSignalSlot for an auxiliary process. Since it
* doesn't have a BackendId, the slot is statically allocated based on
* the auxiliary process type (auxType). Backends use slots indexed
* in the range from 1 to MaxBackends (inclusive), so we use
* the auxiliary process type (MyAuxProcType). Backends use slots
* indexed in the range from 1 to MaxBackends (inclusive), so we use
* MaxBackends + AuxProcType + 1 as the index of the slot for an
* auxiliary process.
*
* This will need rethinking if we ever want more than one of a
* particular auxiliary process type.
*/
ProcSignalInit(MaxBackends + auxType + 1);
ProcSignalInit(MaxBackends + MyAuxProcType + 1);
/* finish setting up bufmgr.c */
InitBufferPoolBackend();
@ -396,7 +400,7 @@ AuxiliaryProcessMain(int argc, char *argv[])
*/
SetProcessingMode(NormalProcessing);
switch (auxType)
switch (MyAuxProcType)
{
case CheckerProcess:
/* don't set signals, they're useless here */
@ -436,7 +440,7 @@ AuxiliaryProcessMain(int argc, char *argv[])
proc_exit(1); /* should never return */
default:
elog(PANIC, "unrecognized process type: %d", auxType);
elog(PANIC, "unrecognized process type: %d", (int) MyAuxProcType);
proc_exit(1);
}
}