diff options
author | Simon Riggs <simon@2ndQuadrant.com> | 2011-09-08 12:03:28 +0100 |
---|---|---|
committer | Simon Riggs <simon@2ndQuadrant.com> | 2011-09-08 12:03:28 +0100 |
commit | 7c24bac64c3828d651abfd5e34bd0e0031ab9946 (patch) | |
tree | 5d9b7f764b4f5e7bc9f724b47138e4f6f447b0ed /src | |
parent | 2ab199b354135f199a895c4ee61c521b03a4d321 (diff) | |
download | postgresql-7c24bac64c3828d651abfd5e34bd0e0031ab9946.tar.gz postgresql-7c24bac64c3828d651abfd5e34bd0e0031ab9946.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/xlog.c | 2 | ||||
-rw-r--r-- | src/backend/storage/lmgr/proc.c | 43 | ||||
-rw-r--r-- | src/include/storage/proc.h | 6 |
3 files changed, 50 insertions, 1 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index bb8971ce91c..3da118b14ed 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -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; diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c index 4ae977154ac..3248e136c9a 100644 --- a/src/backend/storage/lmgr/proc.c +++ b/src/backend/storage/lmgr/proc.c @@ -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 diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index b250d3f0f2d..e586572ef86 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -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); |