aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSimon Riggs <simon@2ndQuadrant.com>2011-09-08 12:03:28 +0100
committerSimon Riggs <simon@2ndQuadrant.com>2011-09-08 12:03:28 +0100
commit7c24bac64c3828d651abfd5e34bd0e0031ab9946 (patch)
tree5d9b7f764b4f5e7bc9f724b47138e4f6f447b0ed /src
parent2ab199b354135f199a895c4ee61c521b03a4d321 (diff)
downloadpostgresql-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.c2
-rw-r--r--src/backend/storage/lmgr/proc.c43
-rw-r--r--src/include/storage/proc.h6
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);