PublishStartupProcessInformation() to avoid rare hang in recovery.

Bgwriter could cause hang in recovery during page concurrent cleaning.

Bug report and testing by Bernd Helmle, fix by me
This commit is contained in:
Simon Riggs 2011-09-08 12:03:28 +01:00
parent 2ab199b354
commit 7c24bac64c
3 changed files with 50 additions and 1 deletions

View File

@ -44,6 +44,7 @@
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/pmsignal.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/smgr.h"
#include "storage/spin.h"
@ -5569,6 +5570,7 @@ StartupXLOG(void)
*/
if (InArchiveRecovery && IsUnderPostmaster)
{
PublishStartupProcessInformation();
SetForwardFsyncRequests();
SendPostmasterSignal(PMSIGNAL_RECOVERY_STARTED);
bgwriterLaunched = true;

View File

@ -1287,12 +1287,53 @@ ProcWaitForSignal(void)
void
ProcSendSignal(int pid)
{
PGPROC *proc = BackendPidGetProc(pid);
PGPROC *proc = NULL;
proc = BackendPidGetProc(pid);
if (proc == NULL)
{
/* use volatile pointer to prevent code rearrangement */
volatile PROC_HDR *procglobal = ProcGlobal;
SpinLockAcquire(ProcStructLock);
/*
* Check to see whether it is the Startup process we wish to signal.
* This call is made by the buffer manager when it wishes to wake up a
* process that has been waiting for a pin in so it can obtain a
* cleanup lock using LockBufferForCleanup(). Startup is not a normal
* backend, so BackendPidGetProc() will not return any pid at all. So
* we remember the information for this special case.
*/
if (pid == procglobal->startupProcPid)
proc = procglobal->startupProc;
SpinLockRelease(ProcStructLock);
}
if (proc != NULL)
PGSemaphoreUnlock(&proc->sem);
}
/*
* Record the PID and PGPROC structures for the Startup process, for use in
* ProcSendSignal(). See comments there for further explanation.
*/
void
PublishStartupProcessInformation(void)
{
/* use volatile pointer to prevent code rearrangement */
volatile PROC_HDR *procglobal = ProcGlobal;
SpinLockAcquire(ProcStructLock);
procglobal->startupProc = MyProc;
procglobal->startupProcPid = MyProcPid;
SpinLockRelease(ProcStructLock);
}
/*****************************************************************************
* SIGALRM interrupt support

View File

@ -133,6 +133,11 @@ typedef struct PROC_HDR
PGPROC *autovacFreeProcs;
/* Current shared estimate of appropriate spins_per_delay value */
int spins_per_delay;
/* PGPROC of Startup process */
PGPROC *startupProc;
/* Pid of Startup process */
int startupProcPid;
} PROC_HDR;
/*
@ -175,6 +180,7 @@ extern void LockWaitCancel(void);
extern void ProcWaitForSignal(void);
extern void ProcSendSignal(int pid);
extern void PublishStartupProcessInformation(void);
extern bool enable_sig_alarm(int delayms, bool is_statement_timeout);
extern bool disable_sig_alarm(bool is_statement_timeout);